""" Matrix multiplication for nested list matrices. This module contains the :func:`matmul` function, which multiplies two matrices represented as nested Python lists. The matrices are expected to be rectangular (each sub‑list has the same length). A :class:`ValueError` is raised if the inner dimensions do not match. Example ------- >>> a = [[1, 2], [3, 4]] >>> b = [[5, 6], [7, 8]] >>> matmul(a, b) [[19.0, 22.0], [43.0, 50.0]] The function is intentionally simple and performs no type checking of the inner elements; it simply forwards the arithmetic operations to Python's built‑in integer and float handling. """ import math from tabulate import tabulate def rot_2D(theta: float) -> list[list[float]]: """Return the 2‑D rotation matrix for a given angle. Parameters ---------- theta : float Angle in radians to rotate counter‑clockwise around the origin. Returns ------- list[list[float]] 2x2 rotation matrix Examples -------- >>> rot_2D(0) # identity [[1.0, -0.0], [0.0, 1.0]] """ c = math.cos(theta) s = math.sin(theta) return [[c, -s], [s, c]] def matmul(a: list[list[float | int]], b: list[list[float | int]]) -> list[list[float]]: """Return the matrix product of *a* and *b*. Parameters ---------- a : list[list[float | int]] First matrix, shape ``(m, n)``. b : list[list[float | int]] Second matrix, shape ``(n, p)``. Returns ------- list[list[float]] The result matrix of shape ``(m, p)``. Raises ------ ValueError If the number of columns of ``a`` does not equal the number of rows of ``b``. """ n_cols_a = len(a[0]) if a else 0 n_rows_b = len(b) if n_cols_a != n_rows_b: raise ValueError( f"inner dimensions must match: {n_cols_a} (a columns) != {n_rows_b} (b rows)" ) m = len(a) p = len(b[0]) if b else 0 # Pre‑allocate result matrix result: list[list[float]] = [[0.0 for _ in range(p)] for _ in range(m)] for i in range(m): for k in range(n_cols_a): # using k as column index of a, row of b a_val = a[i][k] for j in range(p): result[i][j] += a_val * b[k][j] return result def transpose(matrix: list[list[float | int]]) -> list[list[float | int]]: """Return the transpose of the given matrix. Parameters ---------- matrix : list[list[float | int]] Matrix to transpose. All rows must have the same length. Returns ------- list[list[float | int]] Transposed matrix. Raises ------ ValueError If ``matrix`` is empty or rows have differing lengths. Examples -------- >>> mat = [[1, 2, 3], [4, 5, 6]] >>> transpose(mat) [[1, 4], [2, 5], [3, 6]] """ if not matrix: raise ValueError("Matrix must not be empty") row_length = len(matrix[0]) if any(len(row) != row_length for row in matrix): raise ValueError("All rows must have the same number of columns") return [list(col) for col in zip(*matrix)] if __name__ == "__main__": matrix_a = [ [3, 4, -1, 4], [-2, 2, 5, 1], ] matrix_b = [ [1, 3, -2], [2, 5, 1], [-1, 4, -4], [2, 3, 6], ] matrix = [ [1, 2, 3], [4, 5, 6], ] print("Transposed Matrix:\n", transpose(matrix)) print("\nMatrix multiplication result:\n") matrix_c = matmul(matrix_a, matrix_b) for row in matrix_c: print(row) print("\nRotation matrix 90°:\n", rot_2D(math.pi / 2)) print(tabulate(rot_2D(1.0)))