Skip to content

Instantly share code, notes, and snippets.

@unixpickle
Created June 19, 2025 19:56
Show Gist options
  • Save unixpickle/61b4a909ddaee4a2d0a745b53b5e267b to your computer and use it in GitHub Desktop.
Save unixpickle/61b4a909ddaee4a2d0a745b53b5e267b to your computer and use it in GitHub Desktop.
LU factorization
import Accelerate
private let Epsilon: Double = 1e-8
private enum LUFactorizationResult {
case success(LUFactorization)
case singular(Int)
}
private struct LUFactorization {
let rows: Int
let cols: Int
var values: [Double]
var pivots: [__CLPK_integer]
mutating func apply(_ mat: inout ColMajorMatrix) {
var nrhs = __CLPK_integer(mat.cols)
var ldb = __CLPK_integer(mat.rows)
var lda = __CLPK_integer(mat.cols)
var n1 = __CLPK_integer(cols)
var info: __CLPK_integer = 0
var order = CChar("N")!
dgetrs_(&order, &n1, &nrhs, &values, &lda, &pivots, &mat.values, &ldb, &info)
assert(info == 0)
}
}
private struct ColMajorMatrix {
let rows: Int
let cols: Int
var values: [Double]
init(rows: Int, cols: Int) {
self.rows = rows
self.cols = cols
self.values = [Double](repeating: 0, count: rows * cols)
}
subscript(_ row: Int, _ col: Int) -> Double {
get {
assert(row >= 0 && row < rows && col >= 0 && col < cols)
return values[row + col * rows]
}
set {
assert(row >= 0 && row < rows && col >= 0 && col < cols)
values[row + col * rows] = newValue
}
}
func lu() -> LUFactorizationResult {
var newValues = values
// Compute LU factorization
var n1 = __CLPK_integer(rows)
var n2 = __CLPK_integer(cols)
var lda = n1
var pivots = [__CLPK_integer](repeating: 0, count: min(rows, cols))
var info: __CLPK_integer = 0
dgetrf_(&n1, &n2, &newValues, &lda, &pivots, &info)
if info != 0 {
assert(info > 0)
return .singular(Int(info) - 1)
} else {
return .success(LUFactorization(rows: rows, cols: cols, values: newValues, pivots: pivots))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment