Compute the Singular Value Decomposition of a 2x2 matrix manually, returning U, Sigma, and V^T such that A = U Sigma V^T.
import numpy as np
def svd_2x2(A: list[list[float]]) -> tuple:
A = np.array(A, dtype=float)
# Compute A^T A
ATA = A.T @ A
# Eigendecomposition of A^T A
eigenvalues, V = np.linalg.eigh(ATA)
# Sort eigenvalues descending
idx = np.argsort(eigenvalues)[::-1]
eigenvalues = eigenvalues[idx]
V = V[:, idx]
# Singular values
singular_values = np.sqrt(np.maximum(eigenvalues, 0))
Sigma = np.diag(singular_values)
# Compute U
U = np.zeros((2, 2), dtype=float)
for i in range(2):
if singular_values[i] > 1e-10:
U[:, i] = (A @ V[:, i]) / singular_values[i]
else:
# For zero singular values, pick an orthogonal vector
if i > 0:
U[:, i] = np.array([-U[1, 0], U[0, 0]])
# Ensure right-handed coordinate systems
if np.linalg.det(U) < 0:
U[:, -1] *= -1
if np.linalg.det(V) < 0:
V[:, -1] *= -1
return (
np.round(U, 4).tolist(),
np.round(Sigma, 4).tolist(),
np.round(V.T, 4).tolist()
)