Files
matrixmania/compute.py
T
2026-10-15 16:52:02 +02:00

102 lines
2.7 KiB
Python

import math
def matmul(a: list[list[float]], b: list[list[float]]) -> list[list[float]]:
"""Multiply two non-empty rectangular matrices.
Args:
a: The left matrix.
b: The right matrix.
Returns:
The matrix product a * b.
Raises:
ValueError: If either matrix is empty or ragged, or if their
dimensions are incompatible.
"""
_validate_matrix(a, "a")
_validate_matrix(b, "b")
if len(a[0]) != len(b):
raise ValueError(
"Matrix dimensions are incompatible: the number of columns in a "
"must equal the number of rows in b."
)
return [
[
sum(a_row[index] * b[index][column] for index in range(len(b)))
for column in range(len(b[0]))
]
for a_row in a
]
def transpose(matrix: list[list[float]]) -> list[list[float]]:
"""Return the transpose of a non-empty rectangular matrix.
Args:
matrix: A matrix represented as rows of numbers.
Returns:
A new matrix whose rows are the columns of matrix.
Raises:
ValueError: If the matrix is empty or its rows have different lengths.
"""
_validate_matrix(matrix, "matrix")
return [list(column) for column in zip(*matrix)]
def rot_2D(angle: float) -> list[list[float]]:
"""Return the 2D rotation matrix for a given angle in radians.
Args:
angle: The rotation angle in radians.
Returns:
The rotation matrix for rotating points counterclockwise.
"""
return [
[math.cos(angle), -math.sin(angle)],
[math.sin(angle), math.cos(angle)]
]
def _validate_matrix(matrix: list[list[float]], name: str) -> None:
"""Raise ValueError unless matrix is non-empty and rectangular."""
if not matrix:
raise ValueError(f"Matrix {name} must be non-empty.")
column_count = len(matrix[0])
if column_count == 0:
raise ValueError(f"Matrix {name} must have at least one column.")
if any(len(row) != column_count for row in matrix):
raise ValueError(f"Matrix {name} must have rows of equal length.")
if __name__ == "__main__":
first = [[1, 2, 3], [4, 5, 6]]
second = [[7, 8], [9, 10], [11.0, 12.0]]
assert matmul(first, second) == [
[58.0, 64.0],
[139.0, 154.0]
]
print("Matrix product:", matmul(first, second))
try:
matmul([[1, 2]], [[1, 2]])
except ValueError as error:
print("Expected error:", error)
else:
raise AssertionError(
"Expected a ValueError for incompatible dimensions."
)
assert transpose(first) == [
[1, 4],
[2, 5],
[3, 6]
]
print("Transpose:", transpose(first))