create a wrapper for cblas_sgemm that takes in two matrices and has the declaration: func sgemm(a: matrix, b: matrix, transposea: bool, transposeb: bool, alpha: float, beta: float) -> matrix in swift

Below is a possible implementation of a sgemm function that wraps cblas_sgemm:

main.swift
import Accelerate

typealias Matrix = [Float]

func sgemm(a: Matrix, b: Matrix, transposea: Bool, transposeb: Bool, alpha: Float, beta: Float) -> Matrix {
    precondition(!a.isEmpty, "a must not be empty")
    precondition(!b.isEmpty, "b must not be empty")
    
    let m = transposea ? a[0].count : a.count
    let n = transposeb ? b.count : b[0].count
    let k = transposea ? a.count : a[0].count
    precondition(k == (transposeb ? b[0].count : b.count), "Invalid matrix dimensions")
    
    var c = Matrix(repeating: 0, count: m * n)
    cblas_sgemm(CblasRowMajor, transposea ? CblasTrans : CblasNoTrans, transposeb ? CblasTrans : CblasNoTrans,
                Int32(m), Int32(n), Int32(k),
                alpha, a, transposea ? Int32(k) : Int32(m),
                       b, transposeb ? Int32(n) : Int32(k),
                beta, &c, Int32(n))
    
    return c
}
875 chars
23 lines

This function takes in two matrices a and b, and returns their matrix product c such that c = alpha * op(a) · op(b) + beta * c, where op(a) and op(b) are a and b if their corresponding transpose flags are false, and their transposes otherwise.

The transpose flags transposea and transposeb indicate whether the matrices a and b should be transposed before multiplication. The scalars alpha and beta are used to scale the matrices, with beta=0 corresponding to an overwrite of c.

The function performs some dimension checks to ensure that the matrix multiplication is valid, and uses the Accelerate framework's cblas_sgemm function to perform the actual computation. Note that the matrix dimensions and strides are interpreted assuming a row-major memory layout.

gistlibby LogSnag