Erster Stand: compute.py
This commit is contained in:
commit
db8c5c3032
4 files changed
+140
No files matched your search
@@ -0,0 +1,3 @@
|
|||||||
|
[project]
|
||||||
|
name = "matrixmania"
|
||||||
|
version = "0.1.0"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
.venv/
|
||||||
|
__pycache__/
|
||||||
|
.env
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# Regeln für dieses Projekt
|
||||||
|
- Code nach PEP 8, Zeilenlänge maximal 88 Zeichen.
|
||||||
|
- Jede Funktion und Methode hat einen Docstring und Type Hints.
|
||||||
|
- Vor jedem Commit: `ruff check` und `ruff format`.
|
||||||
+130
@@ -0,0 +1,130 @@
|
|||||||
|
"""Computational utilities for matrix operations and 2D transformations.
|
||||||
|
|
||||||
|
Functions:
|
||||||
|
matmul(A, B)
|
||||||
|
Multiply two matrices represented as list of lists.
|
||||||
|
transpose(matrix)
|
||||||
|
Return the transpose of a matrix.
|
||||||
|
rot_2D(theta)
|
||||||
|
Return the 2D rotation matrix for a given angle theta.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import List
|
||||||
|
import math
|
||||||
|
|
||||||
|
Matrix = List[List[float]]
|
||||||
|
|
||||||
|
def transpose(matrix: Matrix) -> Matrix:
|
||||||
|
"""Return the transpose of *matrix*.
|
||||||
|
|
||||||
|
The matrix must be non‑empty and rectangular; this is validated
|
||||||
|
by the existing ``_check_matrix`` helper.
|
||||||
|
"""
|
||||||
|
_check_matrix(matrix)
|
||||||
|
rows, cols = len(matrix), len(matrix[0])
|
||||||
|
return [[matrix[i][j] for i in range(rows)] for j in range(cols)]
|
||||||
|
|
||||||
|
def rot_2D(theta: float) -> Matrix:
|
||||||
|
"""Return the 2D rotation matrix for a given angle theta (in radians).
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
theta : float
|
||||||
|
Rotation angle in radians.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Matrix
|
||||||
|
A 2x2 rotation matrix [[cos(theta), -sin(theta)], [sin(theta), cos(theta)]].
|
||||||
|
"""
|
||||||
|
c = math.cos(theta)
|
||||||
|
s = math.sin(theta)
|
||||||
|
return [
|
||||||
|
[c, -s],
|
||||||
|
[s, c]
|
||||||
|
]
|
||||||
|
|
||||||
|
def _check_matrix(matrix: Matrix) -> None:
|
||||||
|
"""Ensure all rows in *matrix* are lists of floats and of equal length.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If *matrix* is empty, contains non‑list rows,
|
||||||
|
non‑float elements, or uneven row lengths.
|
||||||
|
"""
|
||||||
|
if not matrix:
|
||||||
|
raise ValueError("Matrix must not be empty")
|
||||||
|
row_len = None
|
||||||
|
for row_idx, row in enumerate(matrix):
|
||||||
|
if not isinstance(row, list):
|
||||||
|
raise ValueError(f"Row {row_idx} is not a list")
|
||||||
|
if row_len is None:
|
||||||
|
row_len = len(row)
|
||||||
|
if row_len == 0:
|
||||||
|
raise ValueError("Rows must contain at least one element")
|
||||||
|
elif len(row) != row_len:
|
||||||
|
raise ValueError(
|
||||||
|
f"Row {row_idx} length {len(row)} differs from expected {row_len}"
|
||||||
|
)
|
||||||
|
for col_idx, item in enumerate(row):
|
||||||
|
if not isinstance(item, (int, float)):
|
||||||
|
raise ValueError(
|
||||||
|
f"Element at ({row_idx},{col_idx}) is not a number"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def matmul(A: Matrix, B: Matrix) -> Matrix:
|
||||||
|
"""Return the matrix product of *A* and *B*.
|
||||||
|
|
||||||
|
The matrices must be compatible for multiplication, i.e. the
|
||||||
|
number of columns in *A* must equal the number of rows in *B*.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
A, B : Matrix
|
||||||
|
Two‑dimensional lists of numeric values.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Matrix
|
||||||
|
Resulting matrix of dimensions ``len(A) x len(B[0])``.
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
ValueError
|
||||||
|
If either input is malformed (non‑uniform rows, empty,
|
||||||
|
non‑numeric entries) or if the dimensions are incompatible.
|
||||||
|
"""
|
||||||
|
_check_matrix(A)
|
||||||
|
_check_matrix(B)
|
||||||
|
|
||||||
|
a_rows, a_cols = len(A), len(A[0])
|
||||||
|
b_rows, b_cols = len(B), len(B[0])
|
||||||
|
|
||||||
|
if a_cols != b_rows:
|
||||||
|
raise ValueError(
|
||||||
|
f"Cannot multiply: {a_rows}x{a_cols} matrix A with {b_rows}x{b_cols} matrix B"
|
||||||
|
)
|
||||||
|
|
||||||
|
result: Matrix = []
|
||||||
|
for i in range(a_rows):
|
||||||
|
row: List[float] = []
|
||||||
|
for j in range(b_cols):
|
||||||
|
s = 0.0
|
||||||
|
for k in range(a_cols):
|
||||||
|
s += A[i][k] * B[k][j]
|
||||||
|
row.append(s)
|
||||||
|
result.append(row)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Test für rot_2D (z. B. Rotation um 90 Grad = pi / 2)
|
||||||
|
theta = math.pi / 2
|
||||||
|
R = rot_2D(theta)
|
||||||
|
print("Rotationsmatrix für 90 Grad:", R)
|
||||||
|
|
||||||
|
# Einen Punkt (Vektor) als 2x1 Matrix rotieren: [ [x], [y] ]
|
||||||
|
point = [[1.0], [0.0]] # Punkt auf der x-Achse bei x=1, y=0
|
||||||
|
rotated_point = matmul(R, point)
|
||||||
|
print("Gedrehter Punkt (erwartet y=1, x=0):", rotated_point)
|
||||||
Reference in new issue
Block a user