files added, compute modified
This commit is contained in:
1 parent
806434d813
commit
ebd75fe26e
9 files changed
+527
No files matched your search
@@ -0,0 +1,145 @@
|
||||
"""Compute operations for matrices.
|
||||
|
||||
This module provides public functions for matrix multiplication, transposition,
|
||||
matrix rotation, and generating 2D and 3D rotation matrices as well as projections.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
from typing import List
|
||||
|
||||
|
||||
def matmul(
|
||||
matrix_a: List[List[float]], matrix_b: List[List[float]]
|
||||
) -> List[List[float]]:
|
||||
"""Multiply two 2D matrices.
|
||||
|
||||
Both matrices are expected to be non‑empty and to have consistent row
|
||||
lengths. The number of columns in ``matrix_a`` must equal the number of
|
||||
rows in ``matrix_b``.
|
||||
|
||||
Args:
|
||||
matrix_a: A matrix of shape (m, n) represented as a list of m rows.
|
||||
matrix_b: A matrix of shape (n, p) represented as a list of n rows.
|
||||
|
||||
Returns:
|
||||
A new matrix of shape (m, p) containing the product ``matrix_a @ matrix_b``.
|
||||
|
||||
Raises:
|
||||
ValueError: If either matrix is empty or dimensions do not match.
|
||||
"""
|
||||
if not matrix_a or not matrix_b:
|
||||
raise ValueError("Input matrices must not be empty.")
|
||||
|
||||
n_cols_a = len(matrix_a[0])
|
||||
|
||||
if any(len(row) != n_cols_a for row in matrix_a):
|
||||
raise ValueError("All rows of matrix_a must have the same number of columns.")
|
||||
|
||||
n_rows_b = len(matrix_b)
|
||||
|
||||
if n_cols_a != n_rows_b:
|
||||
raise ValueError(
|
||||
f"Matrix dimension mismatch: matrix_a columns {n_cols_a} != matrix_b rows {n_rows_b}"
|
||||
)
|
||||
|
||||
n_cols_b = len(matrix_b[0])
|
||||
|
||||
if any(len(row) != n_cols_b for row in matrix_b):
|
||||
raise ValueError("All rows of matrix_b must have the same number of columns.")
|
||||
|
||||
result: List[List[float]] = []
|
||||
for i in range(len(matrix_a)):
|
||||
row: List[float] = []
|
||||
for j in range(n_cols_b):
|
||||
elem = sum(matrix_a[i][k] * matrix_b[k][j] for k in range(n_cols_a))
|
||||
row.append(elem)
|
||||
result.append(row)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def transpose(matrix: List[List[float]]) -> List[List[float]]:
|
||||
"""Return the transpose of a 2D matrix."""
|
||||
if not matrix:
|
||||
raise ValueError("Cannot transpose an empty matrix.")
|
||||
|
||||
n_rows = len(matrix)
|
||||
n_cols = len(matrix[0])
|
||||
|
||||
if any(len(row) != n_cols for row in matrix):
|
||||
raise ValueError("All rows of the matrix must have the same number of columns.")
|
||||
|
||||
return [[matrix[i][j] for i in range(n_rows)] for j in range(n_cols)]
|
||||
|
||||
|
||||
def rotate_clockwise(matrix: List[List[float]]) -> List[List[float]]:
|
||||
"""Rotate a square matrix 90 degrees clockwise."""
|
||||
if not matrix:
|
||||
raise ValueError("Cannot rotate an empty matrix.")
|
||||
|
||||
n_cols = len(matrix[0])
|
||||
if any(len(row) != n_cols for row in matrix):
|
||||
raise ValueError("All rows of the matrix must have the same number of columns.")
|
||||
|
||||
transposed = transpose(matrix)
|
||||
return [row[::-1] for row in transposed]
|
||||
|
||||
|
||||
def rot_2D(theta: float) -> List[List[float]]:
|
||||
"""Return the 2D rotation matrix for a given angle in degrees."""
|
||||
rad = math.radians(theta)
|
||||
c = math.cos(rad)
|
||||
s = math.sin(rad)
|
||||
return [[c, -s], [s, c]]
|
||||
|
||||
|
||||
def rot_3D(angle: float, axis: str) -> list[list[float]]:
|
||||
"""Erzeugt eine 3D-Rotationsmatrix um die angegebene Achse ('x', 'y' oder 'z')."""
|
||||
rad = math.radians(angle)
|
||||
c, s = math.cos(rad), math.sin(rad)
|
||||
|
||||
axis = axis.lower()
|
||||
if axis == 'x':
|
||||
return [
|
||||
[1.0, 0.0, 0.0],
|
||||
[0.0, c, -s],
|
||||
[0.0, s, c]
|
||||
]
|
||||
elif axis == 'y':
|
||||
return [
|
||||
[c, 0.0, s],
|
||||
[0.0, 1.0, 0.0],
|
||||
[-s, 0.0, c]
|
||||
]
|
||||
elif axis == 'z':
|
||||
return [
|
||||
[c, -s, 0.0],
|
||||
[s, c, 0.0],
|
||||
[0.0, 0.0, 1.0]
|
||||
]
|
||||
else:
|
||||
raise ValueError("Achse muss 'x', 'y' oder 'z' sein.")
|
||||
|
||||
|
||||
def project_ortho(point: tuple[float, float, float], scale: float = 1.0) -> tuple[float, float]:
|
||||
"""Projiziert einen 3D-Punkt orthogonal auf eine 2D-Ebene und skaliert ihn."""
|
||||
x, y, z = point
|
||||
return (x * scale, y * scale)
|
||||
|
||||
def project_perspective(point: tuple[float, float, float], distance: float = 200.0, scale: float = 1.0) -> tuple[float, float]:
|
||||
"""Projiziert einen 3D-Punkt perspektivisch auf eine 2D-Fläche."""
|
||||
x, y, z = point
|
||||
# Verhindert Division durch 0, falls z genau bei -distance liegt
|
||||
factor = distance / (distance + z) if (distance + z) != 0 else 1.0
|
||||
return (x * factor * scale, y * factor * scale)
|
||||
|
||||
if __name__ == "__main__":
|
||||
a = [[1, 2, 3], [4, 5, 6]]
|
||||
b = [[7, 8], [9, 10], [11, 12]]
|
||||
|
||||
print("matmul(a, b):", matmul(a, b))
|
||||
print("transpose(a):", transpose(a))
|
||||
|
||||
# Teste deine Tests mit: python -m pytest
|
||||
Reference in new issue
Block a user