Skip to content

Commit

Permalink
Add a transpose method for Matrix struct
Browse files Browse the repository at this point in the history
  • Loading branch information
wigging committed Jan 1, 2025
1 parent ed0c84a commit 2f79558
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 4 deletions.
8 changes: 7 additions & 1 deletion Sources/MatrixModule/Matrix.swift
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,16 @@ extension Matrix where Scalar: MatrixArithmetic {
}

extension Matrix where Scalar: MatrixAlgebra {

/// The Euclidean norm of the matrix. Also known as the 2-norm or maximum singular value.
/// - Returns: The matrix norm.
public func norm() -> Scalar {
Scalar.norm(self)
}

/// Transpose the matrix and return the result.
/// - Returns: The transposed matrix.
public func transpose() -> Matrix {
Scalar.transpose(self)
}
}
29 changes: 27 additions & 2 deletions Sources/MatrixModule/MatrixAlgebra.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,59 @@ import Accelerate

public protocol MatrixAlgebra {
static func norm(_ a: Matrix<Self>) -> Self
static func transpose(_ a: Matrix<Self>) -> Matrix<Self>
}

extension Int: MatrixAlgebra {

public static func norm(_ a: Matrix<Int>) -> Int {
var sumOfSquares = 0

for i in 0..<a.rows {
for j in 0..<a.columns {
sumOfSquares &+= a[i, j] * a[i, j]
}
}

let result = sqrt(Float(sumOfSquares))
return Int(result)
}

public static func transpose(_ a: Matrix<Int>) -> Matrix<Int> {
var transposed = Matrix(like: a)
for i in 0..<a.rows {
for j in 0..<a.columns {
transposed[j, i] = a[i, j]
}
}
return transposed
}
}

extension Float: MatrixAlgebra {

public static func norm(_ a: Matrix<Float>) -> Float {
cblas_snrm2(a.buffer.count, a.buffer.baseAddress, 1)
}

public static func transpose(_ a: Matrix<Float>) -> Matrix<Float> {
let m = vDSP_Length(a.columns)
let n = vDSP_Length(a.rows)
let mat = Matrix<Float>(like: a)
vDSP_mtrans(a.buffer.baseAddress!, 1, mat.buffer.baseAddress!, 1, m, n)
return mat
}
}

extension Double: MatrixAlgebra {

public static func norm(_ a: Matrix<Double>) -> Double {
cblas_dnrm2(a.buffer.count, a.buffer.baseAddress, 1)
}

public static func transpose(_ a: Matrix<Double>) -> Matrix<Double> {
let m = vDSP_Length(a.columns)
let n = vDSP_Length(a.rows)
let mat = Matrix<Double>(like: a)
vDSP_mtransD(a.buffer.baseAddress!, 1, mat.buffer.baseAddress!, 1, m, n)
return mat
}
}
2 changes: 1 addition & 1 deletion Sources/VectorModule/Vector.swift
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ extension Vector where Scalar: VectorAlgebra {
public func dot(_ vector: Vector) -> Scalar {
Scalar.dot(self, vector)
}

/// The Euclidean norm of the vector. Also known as the L² norm, 2-norm, vector magnitude, or Euclidean length.
/// - Returns: The vector norm.
public func norm() -> Scalar {
Expand Down
3 changes: 3 additions & 0 deletions Tests/MatrixTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,18 @@ struct MatrixTests {
@Test func integerAlgebra() {
let a = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
#expect(a.norm() == 16)
#expect(a.transpose() == Matrix([[1, 4, 7], [2, 5, 8], [3, 6, 9]]))
}

@Test func floatAlgebra() {
let a = Matrix<Float>([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
#expect(a.norm() == 16.881943)
#expect(a.transpose() == Matrix<Float>([[1, 4, 7], [2, 5, 8], [3, 6, 9]]))
}

@Test func doubleAlgebra() {
let a = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9.0]])
#expect(a.norm() == 16.881943016134134)
#expect(a.transpose() == Matrix([[1, 4, 7], [2, 5, 8], [3, 6, 9.0]]))
}
}

0 comments on commit 2f79558

Please sign in to comment.