Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/run_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,4 @@ jobs:
run: |
magic install
magic run mojo test tests -I .
magic run mojo test tests/core/test_matrix.mojo -I . -D F_CONTIGUOUS
181 changes: 120 additions & 61 deletions numojo/core/matrix.mojo

Large diffs are not rendered by default.

9 changes: 7 additions & 2 deletions numojo/routines/linalg/decompositions.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,8 @@ fn lu_decomposition[
var n = A.shape[0]

# Initiate upper and lower triangular matrices
var U = Matrix.full[dtype](shape=(n, n))
var L = Matrix.full[dtype](shape=(n, n))
var U = Matrix.full[dtype](shape=(n, n), order=A.order())
var L = Matrix.full[dtype](shape=(n, n), order=A.order())

# Fill in L and U
for i in range(0, n):
Expand Down Expand Up @@ -305,6 +305,8 @@ fn partial_pivoting[
"""
var n = A.shape[0]
var P = Matrix.identity[dtype](n)
if A.flags.F_CONTIGUOUS:
A = A.reorder_layout()
var s: Int = 0 # Number of exchanges, for determinant
for col in range(n):
var max_p = abs(A[col, col])
Expand All @@ -318,6 +320,9 @@ fn partial_pivoting[

if max_p_row != col:
s = s + 1
if A.flags.F_CONTIGUOUS:
A = A.reorder_layout()
P = P.reorder_layout()

return Tuple(A^, P^, s)

Expand Down
70 changes: 56 additions & 14 deletions numojo/routines/linalg/products.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -381,25 +381,67 @@ fn matmul[
)
)

var C: Matrix[dtype] = Matrix.zeros[dtype](shape=(A.shape[0], B.shape[1]))
var C: Matrix[dtype]

@parameter
fn calculate_CC(m: Int):
for k in range(A.shape[1]):
if A.flags.C_CONTIGUOUS and B.flags.C_CONTIGUOUS:
C = Matrix.zeros[dtype](shape=(A.shape[0], B.shape[1]), order=B.order())

@parameter
fn dot[simd_width: Int](n: Int):
C._store[simd_width](
m,
n,
C._load[simd_width](m, n)
+ A._load(m, k) * B._load[simd_width](k, n),
)
@parameter
fn calculate_CC(m: Int):
for k in range(A.shape[1]):

vectorize[dot, width](B.shape[1])
@parameter
fn dot[simd_width: Int](n: Int):
C._store[simd_width](
m,
n,
C._load[simd_width](m, n)
+ A._load(m, k) * B._load[simd_width](k, n),
)

vectorize[dot, width](B.shape[1])

parallelize[calculate_CC](A.shape[0], A.shape[0])
parallelize[calculate_CC](A.shape[0], A.shape[0])
elif A.flags.F_CONTIGUOUS and B.flags.F_CONTIGUOUS:
C = Matrix.zeros[dtype](shape=(A.shape[0], B.shape[1]), order=B.order())

@parameter
fn calculate_FF(n: Int):
for k in range(A.shape[1]):

@parameter
fn dot_F[simd_width: Int](m: Int):
C._store[simd_width](
m,
n,
C._load[simd_width](m, n)
+ A._load[simd_width](m, k) * B._load(k, n),
)

vectorize[dot_F, width](A.shape[0])

parallelize[calculate_FF](B.shape[1], B.shape[1])
elif A.flags.C_CONTIGUOUS and B.flags.F_CONTIGUOUS:
C = Matrix.zeros[dtype](shape=(A.shape[0], B.shape[1]), order=B.order())

@parameter
fn calculate_CF(m: Int):
for n in range(B.shape[1]):
var sum: Scalar[dtype] = 0.0

@parameter
fn dot_product[simd_width: Int](k: Int):
sum += (
A._load[simd_width](m, k) * B._load[simd_width](k, n)
).reduce_add()

vectorize[dot_product, width](A.shape[1])
C._store(m, n, sum)

parallelize[calculate_CF](A.shape[0], A.shape[0])

else:
C = matmul(A.reorder_layout(), B)
var _A = A
var _B = B

Expand Down
13 changes: 10 additions & 3 deletions numojo/routines/linalg/solving.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,11 @@ fn inv[dtype: DType](A: Matrix[dtype]) raises -> Matrix[dtype]:
raise Error(
String("{}x{} matrix is not square.").format(A.shape[0], A.shape[1])
)
var order = "F"
if A.flags.C_CONTIGUOUS:
order = "C"

var I = Matrix.identity[dtype](A.shape[0])
var I = Matrix.identity[dtype](A.shape[0], order=order)
var B = solve(A, I)

return B^
Expand Down Expand Up @@ -364,16 +367,20 @@ fn solve[
"""
Solve `AX = Y` using LUP decomposition.
"""
if A.flags.C_CONTIGUOUS != Y.flags.C_CONTIGUOUS:
raise Error("Input matrices A and Y must have the same memory layout")

var U: Matrix[dtype]
var L: Matrix[dtype]

A_pivoted, P, _ = partial_pivoting(A)
L, U = lu_decomposition[dtype](A_pivoted)

var m = A.shape[0]
var n = Y.shape[1]

var Z = Matrix.full[dtype]((m, n))
var X = Matrix.full[dtype]((m, n))
var Z = Matrix.full[dtype]((m, n), order=A.order())
var X = Matrix.full[dtype]((m, n), order=A.order())

var PY = P @ Y

Expand Down
26 changes: 19 additions & 7 deletions numojo/routines/manipulation.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,11 @@ fn transpose[dtype: DType](A: Matrix[dtype]) -> Matrix[dtype]:
"""
Transpose of matrix.
"""
var order = "F"
if A.flags.C_CONTIGUOUS:
order = "C"

var B = Matrix[dtype](Tuple(A.shape[1], A.shape[0]))
var B = Matrix[dtype](Tuple(A.shape[1], A.shape[0]), order=order)

if A.shape[0] == 1 or A.shape[1] == 1:
memcpy(B._buf.ptr, A._buf.ptr, A.size)
Expand Down Expand Up @@ -395,7 +398,9 @@ fn broadcast_to[

fn broadcast_to[
dtype: DType
](A: Matrix[dtype], shape: Tuple[Int, Int]) raises -> Matrix[dtype]:
](
A: Matrix[dtype], shape: Tuple[Int, Int], override_order: String = ""
) raises -> Matrix[dtype]:
"""
Broadcasts the vector to the given shape.

Expand Down Expand Up @@ -426,12 +431,17 @@ fn broadcast_to[
Unhandled exception caught during execution: Cannot broadcast shape 2x2 to shape 4x2!
```
"""
var ord: String
if override_order == "":
ord = A.order()
else:
ord = override_order

var B = Matrix[dtype](shape)
var B = Matrix[dtype](shape, order=ord)
if (A.shape[0] == shape[0]) and (A.shape[1] == shape[1]):
B = A
return A
elif (A.shape[0] == 1) and (A.shape[1] == 1):
B = Matrix.full[dtype](shape, A[0, 0])
B = Matrix.full[dtype](shape, A[0, 0], order=ord)
elif (A.shape[0] == 1) and (A.shape[1] == shape[1]):
for i in range(shape[0]):
memcpy(
Expand All @@ -453,13 +463,15 @@ fn broadcast_to[

fn broadcast_to[
dtype: DType
](A: Scalar[dtype], shape: Tuple[Int, Int]) raises -> Matrix[dtype]:
](A: Scalar[dtype], shape: Tuple[Int, Int], order: String) raises -> Matrix[
dtype
]:
"""
Broadcasts the scalar to the given shape.
"""

var B = Matrix[dtype](shape)
B = Matrix.full[dtype](shape, A)
B = Matrix.full[dtype](shape, A, order=order)
return B^


Expand Down
Loading