import numpy as np

from blatt09 import forward, backward
from blatt10 import QRGivens

def linearLSQNormal(A, b):
    L = np.linalg.cholesky(A.T @ A)
    y = forward(L, A.T @ b)
    return np.linalg.solve(L.T, y)

def linearLSQQR(A, b):
    m, n = A.shape

    Q, R = QRGivens(A)
    return np.linalg.solve(R[:n, :n], Q[:, :n].T @ b)

if __name__ == "__main__":
    A = np.random.standard_normal((100, 10))
    b = np.random.standard_normal(100)

    print(np.linalg.norm(linearLSQNormal(A, b) - linearLSQQR(A, b)))
