I have some functions that are basically wrappers around Accelerate functions (see below). These functions accept a Matrix
type that provides a 2D representation of an Array
. If the input matrix is very large I want to avoid making a copy of it within the function. I just want to reference the matrix values within the function. I do not want to modify the input matrix from inside the function.
import Accelerate
struct Matrix<T> {
let rows: Int
let columns: Int
var values: [T]
init(_ content: [[T]]) {
self.rows = content.count
self.columns = content[0].count
self.values = content.flatMap { $0 }
}
init(rows: Int, columns: Int, values: [T]) {
self.rows = rows
self.columns = columns
self.values = values
}
init(rows: Int, columns: Int, fill: T) {
self.rows = rows
self.columns = columns
self.values = [T](repeating: fill, count: rows * columns)
}
subscript(row: Int, column: Int) -> T {
get { return values[(row * columns) + column] }
set { values[(row * columns) + column] = newValue }
}
}
Here I have a function that divides each element in the matrix by a scalar value. In the function, I create a result
array to store the quotient. Then I create a matrix mat
for the return value. So I basically have two copies of the quotient inside the function: one as the result
array and one as the mat
matrix values. Is there a way to avoid creating the result
array and just create the matrix that is to be returned?
func divide(_ matrix: Matrix<Double>, _ scalar: Double) -> Matrix<Double> {
let result = vDSP.divide(matrix.values, scalar)
let mat = Matrix(rows: matrix.rows, columns: matrix.columns, values: result)
return mat
}
Here is an example where I have a function that multiplies two matrices. In the function, I create two arrays a
and b
and a matrix c
which is the return value. Is there a way to avoid creating these extra arrays which contain the values of the input matrices?
func multiply(_ matrixA: Matrix<Double>, _ matrixB: Matrix<Double>) -> Matrix<Double> {
let a = matrixA.values
let b = matrixB.values
var c = Matrix(rows: matrixA.rows, columns: matrixB.columns, fill: 0.0)
let m = matrixA.rows // rows in matrices A and C
let n = matrixB.columns // columns in matrices B and C
let k = matrixA.columns // columns in matrix A, rows in matrix B
let alpha = 1.0
let beta = 0.0
cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, m, n, k, alpha, a, k, b, n, beta, &c.values, n)
return c
}
These functions get the job done but is there a better way to define them to reduce memory usage; especially when dealing with large matrices? Or do I need to refactor my Matrix
type to work better with Accelerate functions?