# Plinth

Hardware-accelerated matrix library for Swift.

## Installation

### Swift Package Manager

Simply add Plinth to your `Package.swift`

file:

```
let package = Package(
name: "Example",
dependencies: [
.package(url: "https://github.com/dclelland/Plinth.git", from: "2.0.0"),
],
targets: [
.target(name: "Example", dependencies: ["Plinth"])
]
)
```

Then import Plinth into your Swift files:

`import Plinth`

Or for full `ComplexMatrix`

support you should also import `swift-numerics`

, as that's where the `Complex`

type lives.

```
import Plinth
import Numerics
```

## Links

### Dependencies

### References/prior art

- apple/swift-numerics#6 (discussion on adding a
`ShapedArray`

type to`swift-numerics`

) - Jounce/Surge
- hollance/Matrix
- stsievert/swix
- cgarciae/NDArray

## Todo

- Implement Equality/Comparisons extension
- Implement both
`.zeros`

and`.ones`

initializers - Implement exception handling for LAPACK calls
- Implement wrappers for
`vDSP.fill`

,`vDSP.clear`

,`vDSP.window`

,`vDSP.ramp`

,`vDSP.stereoRamp`

- Implement wrapper for
`vDSP.convolve`

- Revisit
`Eigendecomposition.sorted`

, is sorting the eigenvalues by real component or the magnitude preferable? - Write notes on architecture and API design
- Write code examples
- Add Cocoapods support

# Documentation

## Types

### Shape

Defines the shape of a matrix using `rows`

and `columns`

properties.

```
public struct Shape {
public let rows: Int
public let columns: Int
}
```

This includes a number of convenience properties like `count`

, `length`

and `breadth`

; as well as convenience initializers `.row(length:)`

, `.column(length:)`

and `.square(length:)`

.

### Matrix

Generic matrix struct with `Scalar`

type argument and `shape`

and `elements`

properties. Elements are stored as a single array in row-major format.

```
public struct Matrix<Scalar> {
public let shape: Shape
public var elements: [Scalar]
}
```

This also includes a large number of convenience initializers and implementations of typical typeclasses such as `Codable`

and `ExpressibleByArrayLiteral`

.

The `elements`

property is directly mutable but this is ideally to be avoided; matrix regularity is not enforced, except during encoding to or decoding from a serialization format.

There is a computed property `state`

which can be used to check if the matrix is considered to be malformed:

```
let malformed = Matrix<Double>(
shape: .init(rows: 2, columns: 2),
elements: [1.0, 2.0, 3.0, 4.0, 5.0]
)
print(malformed.state)
```

```
> Malformed: Mismatched shape and elements; 2×2 != 5
```

### ComplexMatrix

Generic complex matrix struct encapsulating two separate matrices for the `real`

and `imaginary`

parts.

```
public struct ComplexMatrix<Scalar> where Scalar: Real {
public var real: Matrix<Scalar>
public var imaginary: Matrix<Scalar>
}
```

This also includes a large number of convenience initializers and implementations of typical typeclasses such as `Codable`

and `ExpressibleByArrayLiteral`

.

The `real`

and `imaginary`

properties are also directly mutable; `ComplexMatrix`

has its own `state`

property which can be used to check if the parts are mismatched or malformed.

## Core

### Arithmetic

`+`

and `-`

prefix operators and `+`

, `-`

, `*`

, `/`

infix operators.

Implements fast pointwise arithmetic for combinations of `Scalar`

, `Complex<Scalar>`

, `Matrix<Scalar>`

and `ComplexMatrix<Scalar>`

, where `Scalar`

is `Float`

or `Double`

.

### Conversions

Fast type conversions between the integer types `UInt8`

, `UInt16`

, `UInt32`

, `Int8`

, `Int16`

, `Int32`

and the floating point types `Float`

and `Double`

.

### Functors

Higher-order functions for shape-preserving operations on a matrix's elements.

Includes support for complex matrix operations on `DSPSplitComplex`

/`DSPDoubleSplitComplex`

.

Disclaimer: These are not true functors, Swift lacks higher-kinded types...

### Submatrix

Fast submatrix read/write access using a Swift subscript interface.

Uses Accelerate's

`vDSP_mmov`

/`vDSP_mmovD`

.

### Wrappers

Wrappers over most of the basic `vDSP`

and `vForce`

functions in Accelerate.

## Transformations

### Center

Find the center point of a matrix, given a rounding rule.

### Crop

Crop a matrix towards the center, given a rounding rule.

### Pad

Zero-pad a matrix away from the center, given a rounding rule.

### Reshape

Apply a new shape to a matrix, or reshape it as a single row or column.

This also supports both `.rowMajor`

and `.columnMajor`

orderings.

### Shift

Apply a circular shift to a matrix.

### Concatenate

Concatentate multiple matrices together, row-wise or column-wise.

## Comparisons

### Comparisons

`<`

, `<=`

, `>`

, `>=`

, `==`

, `!==`

infix operators.

Pointwise comparison or equality checks, returning `0.0`

for `false`

and `1.0`

for `true`

.

## Mathematics

### Powers

`**`

infix operator.

Implements fast pointwise power operations for `Scalar`

and `Matrix`

.

Includes special functions for taking integer powers of matrices, for use when recursive application of `vDSP.multiply`

will be faster than `vForce.pow`

(which is quite an expensive operation).

This also supports negative integers by applying `vForce.reciprocal`

to the result.

### Interpolation

Linear interpolate values from a given range to/from `0.0...1.0`

.

This is similar to C++'s

`std::lerp`

.

## Statistics

### Random

Generate matrices populated with random noise.

### Gaussian

Generate matrices populated with Gaussian noise.

This is derived from an answer on the comp.lang.c FAQ.

### Moments

Calculate central and standardized moments; convenience methods for `variance`

, `standardDeviation`

, `skewness`

, and `kurtosis`

.

### Normalization

Normalize a matrix to `0.0...1.0`

using its `minimum()`

and `maximum()`

values; or shift it so that its `mean()`

is centered on zero.

## Linear Algebra

### Zeros

Generate matrices populated by zeros.

### Ones

Generate matrices populated by ones.

### Identity

Generate identity matrices.

### Diagonal

Generate diagonal matrices.

### Transposition

Transpose a matrix.

Uses Accelerate's

`vDSP_mtrans`

/`vDSP_mtransD`

.

### Inversion

Calculate the inverse of a matrix.

Uses LAPACK's

`sgetri_`

/`dgetri_`

for real matrices and`cgetri_`

/`zgetri_`

for complex matrices.

### Multiplication

`<*>`

infix operator.

Implements matrix multiplication.

Uses Accelerate's

`vDSP_mmul`

/`vDSP_mmulD`

for real matrices and`vDSP_zmmul`

/`vDSP_zmmulD`

for complex matrices.

### Division

`/>`

and `</`

infix operators.

Implements left and right matrix division (multiplying by the inverse of a matrix).

### Square Root

Complex square roots.

Formula taken from MATLAB's

`sqrt`

function.

### Exponentiation

Complex exponentials.

Formula taken from MATLAB's

`exp`

function.

### Products

Inner and outer products.

### Eigendecomposition

Calculate the eigendecomposition of a matrix. Includes support for only calculating the necessary components. Also includes support for sorting the eigenvectors by properties of the eigenvalues.

Uses LAPACK's

`sgeev_`

/`dgeev_`

. Swift implementation cribbed from Surge.

### Roots

Calculate the roots of a polynomial by taking the eigenvalues of a companion matrix.

## Signal Processing

### FFT

Forward and inverse two-dimensional fourier transforms.

Includes support for creating, reusing, and destroying your own `FFTSetup`

/`FFTSetupD`

structure.

Some of the inverse fourier transform methods implement energy conservation by dividing by the size of the matrix.

Uses Accelerate's

`vDSP_fft2d_zip`

/`vDSP_fft2d_zipD`

.

### FFTShift

Apply a circular rotation to a frequency-domain matrix so that the DC/DC signal is at the top left of the lower right quadrant.

### Autocorrelation

Calculate the autocorrelation of a matrix by taking the square magnitudes in the frequency domain.