Matrix Multiplication, Division, Addition, and Subtraction in Swift

Apple operating systems like iOS and macOS contain a performance optimized framework called Accelerate for fast matrix operations. This post presents examples for matrix addition, subtraction, multiplication, and division:

  1. Preparing Matrices
  2. Matrix Multiplication
    a. Single Precision Matrix Multiplication
    b. Double Precision Matrix Multiplication
    c. Transpose, Row-Major, and Column-Major Matrix Multiplication Using CBLAS
    d. Element-wise Matrix Multiplication
  3. Element-wise Matrix Division
  4. Matrix Addition
  5. Matrix Subtraction
  6. Sum of All Values In A Matrix

FREE all Swift loading animations.

Loading Animation Example

Follow AdvancedSwift and immediately get access to commented code for these animations that you can use in your projects.

Preparing Matrices

To prepare for matrix arithmetic using Accelerate matrices need to be transformed into a format Accelerate can accept. Two-dimensional matrices first need to be flattened (turned into one-dimensional vectors that represent two-dimension matrices).

The matrix multiplication examples in this post evaluate A * B = C.

import Accelerate

// Define matrix row and column sizes
let M = Int32(3)
let N = Int32(1)
let K = Int32(2)

// Matrix A, a MxK sized matrix
let A: [Float] = [
    [3, 6],
    [1, 5],
    [8, 0]
].flatMap { $0 }

// Matrix B, a KxN sized matrix
let B: [Float] = [
    [2],
    [6]
].flatMap { $0 }

// Matrix C, a MxN sized matrix
var C: [Float] = [
    [0],
    [0],
    [0]
].flatMap { $0 }

Matrix Multiplication

The Accelerate framework contains multiple interfaces for single, double, and element-wise matrix multiplication in Swift.

Single Precision Matrix Multiplication

Use the vDSP_mmul function to perform single precision matrix multiplication:

// Using A, B, C and M, N, K as defined

// The stride is the distance between elements to read. 
// To use all consecutive elements, set the stride to 1.
let aStride = vDSP_Stride(1)
let bStride = vDSP_Stride(1)
let cStride = vDSP_Stride(1)

vDSP_mmul(
    A, aStride,
    B, bStride,
    &C, cStride,
    vDSP_Length(M),
    vDSP_Length(N),
    vDSP_Length(K)
)

// C will be [42.0, 32.0, 16.0]

Double Precision Matrix Multiplication

The process for double precision matrix multiplication using vDSP is the same as single precision except:
a. vDSP_mmulD is used instead of vDSP_mmul
b. A, B, and C must be of type [Double] instead of [Float]

Transpose, Row-Major, and Column-Major Matrix Multiplication Using CBLAS

Accelerate includes another performance optimized interface for matrix multiplication supporting single precision (cblas_sgemm) and double precision (cblas_dgemm) multiplication.

The cblas_sgemm and cblas_dgemm functions include additional configuration options for row-major and column-major data formats, A and/or B matrix transposition, and scaling factors. The cblas functions enable the following matrix multiplication operation: αAB + βC = C

// Using A, B, C and M, N, K as defined

// Row-major indicates the row is contiguous in
// memory. The other option is column-major ordering
let Order = CblasRowMajor

// If matrix A should be transposed
let TransposeA = CblasNoTrans

// If matrix B should be transposed
let TransposeB = CblasNoTrans

// Scaling factor for A * B
let alpha = Float(1.0)

// Scaling factor for matrix C
let beta = Float(1.0)

// In row-major ordering, the number of items
// in a row of matrix A (K)
let lda = K

// In row-major ordering, the number of items
// in a row of matrix B (N)
let ldb = N

// In row-major ordering, the number of items
// in a row of matrix C (N)
let ldc = N

cblas_sgemm(
    Order,
    TransposeA, TransposeB,
    M, N, K,
    alpha,
    A, lda,
    B, ldb,
    beta,
    &C, ldc
)

// C will be [42.0, 32.0, 16.0]

The process for double precision matrix multiplication using CBLAS is the same as single precision except:
a. cblas_dgemm is used instead of cblas_sgemm
b. alpha and beta must be of type Double
c. A, B, and C must be of type [Double] instead of [Float]

Element-wise Matrix Multiplication

To multiply each element in a matrix with a constant value, use vDSP.multiply and pass a constant as the first argument:

let matrix: [Float] = [
    [3, 6], 
    [1, 5]
].flatMap { $0 }

let result = vDSP.multiply(2, matrix)

Element-wise Matrix Division

To divide each element in a matrix with a constant value, use vDSP.divide and pass a constant as the first argument:

let matrix: [Float] = [
    [3, 6], 
    [1, 5]
].flatMap { $0 }

let result = vDSP.divide(2, matrix)

Matrix Addition

Use vDSP.add to add two matrices:

let matrix: [Float] = [
    [3, 6], 
    [1, 5]
].flatMap { $0 }

let result = vDSP.add(matrix, matrix)

Matrix Subtraction

Use vDSP.subtraact to subtract two matrices:

let matrix: [Float] = [
    [3, 6], 
    [1, 5]
].flatMap { $0 }

let result = vDSP.subtract(matrix, matrix)

Sum of All Values In A Matrix

Use vDSP.sum to sum all the values in a matrix:

let matrix: [Float] = [
    [3, 6], 
    [1, 5]
].flatMap { $0 }

let matrixSum = vDSP.sum(matrix)

Performance Optimized Matrix Operations In Swift

That’s it! By using Accelerate and vDSP you can multiply, divide, subtract, and add matrices in Swift in a performance optimized manner.