## Matrix Operations in Swift

I recently completed 10 Days of Statistics on HackerRank. Yay!

In the process, I needed some matrix operations for a medium-difficulty problem. And here they are, code style be damned :

```func transpose(_ matrix: [[Double]]) -> [[Double]] {
let rowCount = matrix.count
let colCount = matrix[0].count
var transposed : [[Double]] = Array(repeating: Array(repeating: 0.0, count: rowCount), count: colCount)
for rowPos in 0..<matrix.count {
for colPos in 0..<matrix[0].count {
transposed[colPos][rowPos] = matrix[rowPos][colPos]
}
}
return transposed
}

func multiply(_ A: [[Double]], _ B: [[Double]]) -> [[Double]] {
let rowCount = A.count
let colCount = B[0].count
var product : [[Double]] = Array(repeating: Array(repeating: 0.0, count: colCount), count: rowCount)
for rowPos in 0..<rowCount {
for colPos in 0..<colCount {
for i in 0..<B.count {
product[rowPos][colPos] += A[rowPos][i] * B[i][colPos]
}
}
}
return product
}

// gauss jordan inversion
func inverse(_ matrix: [[Double]]) -> [[Double]] {
// augment matrix
var matrix = matrix
var idrow = Array(repeating: 0.0, count: matrix.count)
idrow[0] = 1.0
for row in 0..<matrix.count {
matrix[row] += idrow
idrow.insert(0.0, at:0)
idrow.removeLast()
}

// partial pivot
for row1 in 0..<matrix.count {
for row2 in row1..<matrix.count {
if abs(matrix[row1][row1]) < abs(matrix[row2][row2]) {
(matrix[row1],matrix[row2]) = (matrix[row2],matrix[row1])
}
}
}

// forward elimination
for pivot in 0..<matrix.count {
// multiply
let arg = 1.0 / matrix[pivot][pivot]
for col in pivot..<matrix[pivot].count {
matrix[pivot][col] *= arg
}

for row in (pivot+1)..<matrix.count {
let arg = matrix[row][pivot] / matrix[pivot][pivot]
for col in pivot..<matrix[row].count {
matrix[row][col] -= arg * matrix[pivot][col]
}
}
}

// backward elimination
for pivot in (0..<matrix.count).reversed() {
for row in 0..<pivot {
let arg = matrix[row][pivot] / matrix[pivot][pivot]
for col in pivot..<matrix[row].count {
matrix[row][col] -= arg * matrix[pivot][col]
}
}
}

// remove identity
for row in 0..<matrix.count {
for _ in 0..<matrix.count {
matrix[row].remove(at:0)
}
}

return matrix
}

let X = [ [1.0, 2.0, 3.0], [4.0, 5.0, 11.0], [7.0, 8.0, 9.0] ]
let XI = inverse(X)
let I = multiply(X,XI)
print(I)
```

That’s the identity matrix popping out at the end, which validates my implementation.

But what’s this? A 60-line method? Uncle Bob would not be pleased.

Comments should not take the place of good variable/method names. Those section comments give clues as to where my methods should be :

```func augment(_ matrix: [[Double]]) -> [[Double]] {
var augmented = matrix
var idrow = Array(repeating: 0.0, count: matrix.count)
idrow[0] = 1.0
for row in 0..<matrix.count {
augmented[row] += idrow
idrow.insert(0.0, at:0)
idrow.removeLast()
}
return augmented
}

func deaugment(_ matrix: [[Double]]) -> [[Double]] {
var deaugmented = matrix

for row in 0..<matrix.count {
for _ in 0..<matrix.count {
deaugmented[row].remove(at:0)
}
}
return deaugmented
}

func partialPivot(_ matrix: inout [[Double]]) {
for row1 in 0..<matrix.count {
for row2 in row1..<matrix.count {
if abs(matrix[row1][row1]) < abs(matrix[row2][row2]) {
(matrix[row1],matrix[row2]) = (matrix[row2],matrix[row1])
}
}
}
}

func scaleRow(_ matrix: inout [[Double]], row: Int, scale: Double) {
for col in 0..<matrix[row].count {
matrix[row][col] *= scale
}
}

func addRow(_ matrix: inout [[Double]], row: Int, scaledBy: Double, toRow: Int) {
for col in 0..<matrix[row].count {
matrix[toRow][col] += scaledBy * matrix[row][col]
}
}

func pivot(_ matrix: inout [[Double]], row pivotRow: Int, col pivotCol: Int, forward: Bool) {
let scale = 1.0 / matrix[pivotRow][pivotCol]
scaleRow(&matrix, row: pivotRow, scale: scale)

if forward {
for toRow in (pivotRow+1)..<matrix.count {
let scaleBy = -1.0 * matrix[toRow][pivotCol]
addRow(&matrix, row: pivotRow, scaledBy: scaleBy, toRow: toRow)
}
} else {
for toRow in (0..<pivotRow).reversed() {
let scaleBy = -1.0 * matrix[toRow][pivotCol]
addRow(&matrix, row: pivotRow, scaledBy: scaleBy, toRow: toRow)
}
}
}

func gaussJordanInverse(_ matrix: [[Double]]) -> [[Double]] {
var matrix = augment(matrix)
partialPivot(&matrix)

for p in 0..<matrix.count {
pivot(&matrix, row: p, col: p, forward: true)
}

for p in (0..<matrix.count).reversed() {
pivot(&matrix, row: p, col: p, forward: false)
}

matrix = deaugment(matrix)

return matrix
}

let X = [ [1.0, 2.0, 3.0], [4.0, 5.0, 11.0], [7.0, 8.0, 9.0] ]
let XI = gaussJordanInverse(X)
let I = multiply(X,XI)
print(I)
```

Better. Uncle Bob would be proud (or give me credit for trying, anyway).

One more thing : Thanks to StackOverflow user Alexander, I have an even better way to express that pivot loop :

```func pivot(_ matrix: inout [[Double]], row pivotRow: Int, col pivotCol: Int, forward: Bool) {
let scale = 1.0 / matrix[pivotRow][pivotCol]
scaleRow(&matrix, row: pivotRow, scale: scale)

let range = forward ? AnyCollection((pivotRow+1)..<matrix.count) : AnyCollection((0..<pivotRow).reversed())

for toRow in range {
let scaleBy = -1.0 * matrix[toRow][pivotCol]
addRow(&matrix, row: pivotRow, scaledBy: scaleBy, toRow: toRow)
}
}
```

## iOS Williamsburg – Swift Basics

Do you want to learn Swift syntax, have fun, and meet an enthusiastic group of developers? Come by the Williamsburg Library at 515 Scotland Street, Williamsburg, VA, on Saturday, August 12, 2017. We will be going over Swift basics. We have many experienced developers who are eager to share tips and help newcomers.

### iOS development basics.

Saturday, Aug 12, 2017, 10:00 AM

Location details are available to members only.

11 Members Attending

Room c

I hope to see you there!

## iOS Dev Camp DC 2017

It’s tomorrow! See you at iOS Dev Camp DC on Friday, August 3, 2017.

I am looking forward to meeting many talented developers and learning all about who you are and what you do.