def qr_householder(a):
    m, n = a.shape
    t = min(m, n)
    q = np.eye(m)
    r = a.copy()

    for k in range(t - 1):
        # select a column of modified matrix A':
        x = r[k:, [k]]
        # construct first basis vector
        e1 = np.zeros_like(x)
        e1[0] = 1.0
        # determine scaling factor
        alpha = np.linalg.norm(x)
        # construct vector v for Householder reflection
        v = x + np.sign(x[0]) * alpha * e1
        v /= np.linalg.norm(v)

        # construct the Householder matrix
        q_k = np.eye(m - k) - 2.0 * v @ v.T
        # pad with ones and zeros as necessary
        q_k = np.block([[np.eye(k), np.zeros((k, m - k))], [np.zeros((m - k, k)), q_k]])

        q = q @ q_k.T
        r = q_k @ r

    return q, r