Compare commits

...
2 Commits
Author SHA1 Message Date
washingtonta103380 314589c6fb 4 commit praktikum 2026-10-20 21:07:04 +02:00
washingtonta103380 d065d4d17d Add rot_3D and tests for rot_2D/rot_3D 2026-10-20 21:06:16 +02:00
10 changed files with 126 additions and 10 deletions

No files matched your search

+1 -1
View File
@@ -2,7 +2,7 @@
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 3.14" jdkType="Python SDK" />
<orderEntry type="jdk" jdkName="Python 3.13 (PythonProject)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
+1 -1
View File
@@ -3,5 +3,5 @@
<component name="Black">
<option name="sdkName" value="Python 3.14" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.14" project-jdk-type="Python SDK" />
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13 (PythonProject)" project-jdk-type="Python SDK" />
</project>
+5 -1
View File
@@ -1,4 +1,8 @@
# 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`.
- Vor jedem Commit: `ruff check` und `ruff format`.
## Projektstruktur
- Quellcode liegt unter "src/matrixmania/", Tests unter "test/test_matrixmania/"
- Testpakete, Testdateien und Testfunktionen beginnen mit "test_
-2
View File
@@ -1,2 +0,0 @@
print("APOLLO")
print("hallo")
+16
View File
@@ -0,0 +1,16 @@
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"thn": {
"npm": "@ai-sdk/openai-compatible",
"options": {
"baseURL": "http://141.75.33.244:8000/v1",
"apiKey": "sk-QXj1p40XOwNSze_5-eYrBzVh3qIgAfqoWPkAjNVqOS8"
},
"models": {
"gpt-oss:20b": { "name": "GPT-OSS 20B" }
}
}
},
"model": "thn/gpt-oss:20b"
}
+10 -1
View File
@@ -2,4 +2,13 @@
name = "matrixmania"
version = "0.1.0"
dependencies = ["tabulate", "ruff"]
dependencies = ["tabulate", "ruff"]
[project.optional-dependencies]
dev = ["pytest", "ruff", "pytest-cov"]
[tool.pytest.ini_options]
pythonpath = "src"
testpaths = "test"
+1
View File
@@ -0,0 +1 @@
from .compute import matmul, transpose, rot_2D
+34 -4
View File
@@ -1,5 +1,5 @@
import math
from tabulate import tabulate
def matmul(matrix_a: list[list[float | int]], matrix_b: list[list[float | int]]) -> list[list[float | int]]:
"""Multipliziert zwei Matrizen, die als verschachtelte Listen dargestellt sind.
@@ -91,6 +91,37 @@ def rot_2D(theta: float) -> list[list[float]]:
[sin_theta, cos_theta]
]
def rot_3D(angle: float, axis: str) -> list[list[float]]:
"""Gibt die 3D-Rotationsmatrix um eine Koordinatenachse zurück.
Formeln (θ = angle, im Bogenmaß):
R_x(θ) = [[1, 0, 0], [0, cos θ, -sin θ], [0, sin θ, cos θ]]
R_y(θ) = [[cos θ, 0, sin θ], [0, 1, 0], [-sin θ, 0, cos θ]]
R_z(θ) = [[cos θ, -sin θ, 0], [sin θ, cos θ, 0], [0, 0, 1]]
Args:
angle: Der Rotationswinkel in Bogenmaß (Radians).
axis: Die Rotationsachse: "x", "y" oder "z".
Returns:
Die 3x3-Rotationsmatrix als 2D-Liste.
Raises:
ValueError: Wenn axis nicht "x", "y" oder "z" ist.
"""
c = math.cos(angle)
s = math.sin(angle)
if axis == "x":
return [[1.0, 0.0, 0.0], [0.0, c, -s], [0.0, s, c]]
if axis == "y":
return [[c, 0.0, s], [0.0, 1.0, 0.0], [-s, 0.0, c]]
if axis == "z":
return [[c, -s, 0.0], [s, c, 0.0], [0.0, 0.0, 1.0]]
raise ValueError(f"Ungültige Achse '{axis}': erlaubt sind 'x', 'y' oder 'z'.")
if __name__ == "__main__":
@@ -154,8 +185,7 @@ if __name__ == "__main__":
theta = math.pi / 2 #1,57...
print(f"Winkel: {math.degrees(theta)} Grad (pi / 2)")
print(rot_2D(theta))
print(tabulate(rot_2D(1.0)))
print(rot_2D(1.0))
print("hallo")
print("apollo")
View File
Whitespace-only changes.
+58
View File
@@ -0,0 +1,58 @@
import math
import pytest
from matrixmania.compute import matmul, rot_2D, rot_3D, transpose
def assert_matrix_close(actual, expected):
"""Vergleicht zwei Matrizen elementweise mit Toleranz."""
assert len(actual) == len(expected)
for row_a, row_e in zip(actual, expected):
assert row_a == pytest.approx(row_e, abs=1e-9)
# ---------- rot_2D ----------
def test_rot_2D_zero():
assert_matrix_close(rot_2D(0), [[1, 0], [0, 1]])
def test_rot_2D_90_degree():
assert_matrix_close(rot_2D(math.pi / 2), [[0, -1], [1, 0]])
def test_rot_2D_invalid_input():
with pytest.raises(TypeError):
rot_2D("abc")
# ---------- rot_3D ----------
@pytest.mark.parametrize("axis", ["x", "y", "z"])
def test_rot_3D_zero_is_identity(axis):
assert_matrix_close(rot_3D(0, axis), [[1, 0, 0], [0, 1, 0], [0, 0, 1]])
@pytest.mark.parametrize(
"axis, expected",
[
("x", [[1, 0, 0], [0, 0, -1], [0, 1, 0]]),
("y", [[0, 0, 1], [0, 1, 0], [-1, 0, 0]]),
("z", [[0, -1, 0], [1, 0, 0], [0, 0, 1]]),
],
)
def test_rot_3D_90_degree(axis, expected):
assert_matrix_close(rot_3D(math.pi / 2, axis), expected)
@pytest.mark.parametrize("axis", ["x", "y", "z"])
def test_rot_3D_is_orthogonal(axis):
r = rot_3D(1.0, axis)
assert_matrix_close(matmul(r, transpose(r)), [[1, 0, 0], [0, 1, 0], [0, 0, 1]])
@pytest.mark.parametrize("axis", ["w", "X", "", "xy"])
def test_rot_3D_invalid_axis(axis):
with pytest.raises(ValueError):
rot_3D(1.0, axis)