Skip to content

A lightweight, easy-to-use Matrix data structure in pure Swift

License

Notifications You must be signed in to change notification settings

rickwierenga/Matrix.swift

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Matrix.swift is a lightweight, easy-to-use Matrix data structure in pure Swift. The backend is based on Accelerate.framework to run compute intensive operations in parallel. The API is inspired by NumPy.

This is not a fully fledged linear algebra library. If you are looking for one, check out Surge.

Performance

Processing a batch of MNIST-like images (on a 2016 15" MacBook Pro):

let totalSeconds = (0..<100).reduce(0.0) { _,_ in
    let x = Matrix(randomIn: 0...1, rows: 100, columns: 784)
    let w = Matrix(randomIn: 0...1, rows: 784, columns: 10)
    let start = CFAbsoluteTimeGetCurrent()
    _ = x  w
    let end = CFAbsoluteTimeGetCurrent()
    return Double(end - start)
}
print("\(totalSeconds / 100) seconds")
Tool Processing 100 MNIST-like images Supported Platforms Size
Native implementation 4628.63 µs¹ all -
Matrix.swift 1.41 µs¹ macOS, iOS, tvOS, watchOS 16 kB
Swift for TensorFlow 1.04 µs¹ macOS, Ubuntu ~2.4GB
NumPy 69.3 µs¹ macOS, Ubuntu, Windows 88.2MB

¹ On a 2016 15" MacBook Pro, no eGPU

Keep in mind that these tools are designed for different usecases. Which one is the best depends on the project.

Installation

Simply copy the Matrix.swift file into your project.

Usage

Creating a Matrix

From an array

Matrix([1, 2, 3, 4])
Matrix([
  [1, 2],
  [3, 4]
])

Copy another matrix

Matrix(copy: anotherMatrix)

Repeating a number (similar to this). This is an alternative to NumPy zeros or ones.

Matrix(repeating: .pi, rows: 2, columns: 2)

Random

Matrix(randomIn: 0...1, columns: 5, rows: 5)

Indexing / slicing

Matrix.swift has powerful slicing support with Range. Slicing also supports in place assignment.

var m = Matrix([
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
    [10, 11, 12]
])

m[1...3, 1...2] *= 2
Matrix([
    [1.0, 4.0, 6.0],
    [4.0, 10.0, 12.0],
    [7.0, 16.0, 18.0],
    [10.0, 11.0, 12.0],
])

You can assign integers to matrices:

m[...1, 1...] &= 0 // Is equal to: Matrix(repeating: 0, rows: a[...1, 1...].rows, columns: a[...1, 1...].columns)
Matrix([
    [1.0, 0.0, 0.0],
    [4.0, 0.0, 0.0],
    [7.0, 8.0, 9.0],
    [10.0, 11.0, 12.0],
])

Arithmatic

Every usual arithmatic operators +, -, * and / is supported for Matrix-Scalar and Matrix-Matrix computations. Note that these are elementwise if both operands are matrices. +=, -=, *=, •= can be used for in place operations.

is used for matrix multiplication (hint: alt+8).

Other features

Number of elements:

m.size

Sum:

m.sum
m.sum(.rows)
m.sum(.columns)

Max:

m.max(.rows)
m.max(.columns)

Min:

m.min(.rows)
m.min(.columns)

Argmax:

m.argmax(.rows)
m.argmax(.columns)

Argmin:

m.argmin(.rows)
m.argmin(.columns)

Transposition:

m.transposed()

Diagonal:

m.diagonal()

Reversed:

m.reversed()

Count zero / nonzero:

m.countNonzeros()
m.countZeros()

Flipping:

m.flipped(.rows)
m.flipped(.columns)

Flatten:

m.flatten()

Sorting:

m.sorted(.rows, sortOrder: .ascending)
m.sorted(.columns, sortOrder: .descending)

Searching:

m.firstIndex(where: {$0 == 9}) // -> (row: Optional(2), column: Optional(2))

License

Matrix.swift is available under the MIT License. See LICENSE for details.


©2020 Rick Wierenga

Releases

No releases published

Packages

No packages published

Languages