126 lines
2.9 KiB
Python
126 lines
2.9 KiB
Python
"""Utility module providing basic matrix operations.
|
||
|
||
Functions
|
||
---------
|
||
- :func:`matmul` – Multiply two matrices.
|
||
- :func:`transpose` – Transpose a matrix.
|
||
- :func:`rotate` – Rotate a matrix 90° clockwise.
|
||
|
||
All functions work on nested Python lists and perform basic
|
||
validation before operation.
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
Matrix = list[list[float]]
|
||
|
||
def main():
|
||
a = [[1, 2, 3], [4, 5, 6]]
|
||
b = [[7, 8], [10, 11], [12, 13]]
|
||
print(matmul(a,b))
|
||
print(rotate(a))
|
||
print(transpose(a))
|
||
|
||
def matmul(a: Matrix, b: Matrix) -> Matrix:
|
||
"""Return the product of two matrices.
|
||
|
||
Parameters
|
||
----------
|
||
a: Matrix
|
||
Left‑hand matrix (shape ``m × n``).
|
||
b: Matrix
|
||
Right‑hand matrix (shape ``n × p``).
|
||
|
||
Returns
|
||
-------
|
||
Matrix
|
||
Resulting matrix of shape ``m × p``.
|
||
|
||
Raises
|
||
------
|
||
ValueError
|
||
If the inner dimensions of the matrices do not match, or if
|
||
either argument is empty.
|
||
"""
|
||
if not a or not a[0] or not b or not b[0]:
|
||
raise ValueError("Input matrices must be non‑empty")
|
||
|
||
n_cols_a = len(a[0])
|
||
n_rows_b = len(b)
|
||
if n_cols_a != n_rows_b:
|
||
raise ValueError(
|
||
f"Inner dimensions must agree for matrix multiplication: "
|
||
f"{len(a)}×{n_cols_a} and {n_rows_b}×{len(b[0])}"
|
||
)
|
||
|
||
m = len(a)
|
||
p = len(b[0])
|
||
result: Matrix = [[0.0 for _ in range(p)] for _ in range(m)]
|
||
|
||
for i in range(m):
|
||
for j in range(p):
|
||
total = 0.0
|
||
for k in range(n_cols_a):
|
||
total += a[i][k] * b[k][j]
|
||
result[i][j] = total
|
||
return result
|
||
|
||
|
||
def transpose(matrix: Matrix) -> Matrix:
|
||
"""Return the transpose of a matrix.
|
||
|
||
Parameters
|
||
----------
|
||
matrix: Matrix
|
||
A matrix represented as a list of row lists.
|
||
|
||
Returns
|
||
-------
|
||
Matrix
|
||
The transposed matrix.
|
||
|
||
Raises
|
||
------
|
||
ValueError
|
||
If the matrix is empty or rows are not of equal length.
|
||
"""
|
||
if not matrix or not matrix[0]:
|
||
raise ValueError("Input matrix must be non‑empty")
|
||
|
||
row_length = len(matrix[0])
|
||
for row in matrix:
|
||
if len(row) != row_length:
|
||
raise ValueError("All rows in the matrix must have the same length")
|
||
|
||
return [list(col) for col in zip(*matrix)]
|
||
|
||
|
||
def rotate(matrix: Matrix) -> Matrix:
|
||
"""Return the matrix rotated 90 degrees clockwise.
|
||
|
||
This is equivalent to transposing the matrix and then reversing
|
||
each row.
|
||
|
||
Parameters
|
||
----------
|
||
matrix: Matrix
|
||
A matrix represented as a list of row lists.
|
||
|
||
Returns
|
||
-------
|
||
Matrix
|
||
The rotated matrix.
|
||
|
||
Raises
|
||
------
|
||
ValueError
|
||
If the matrix is empty or rows are not of equal length.
|
||
"""
|
||
transposed = transpose(matrix)
|
||
return [list(reversed(row)) for row in transposed]
|
||
|
||
if __name__ == "__main__":
|
||
main()
|
||
|
||
"""End of module"""
|