the orthogonality of the resulting $Q$ factor suffers with the condition number of the matrix. Another method is based on Givens rotations, where entries in the subdiagonal part of the matrix are zeroed out to form the triangular factor and the rotations are accumulated to form the orthogonal factor. This method is very stable and has more parallelism than the Householder method; however it is more expensive, doing about 50% more work, and it is more challenging to extract the parallelism efficiently on the GPU. For our implementation, we rely on the Householder method due to its numerical stability and simplicity. The method is described in pseudo-code in Algorithm \[alg:qr\].

\[t\]

$[Q, R] = [I, A]$ $v = \text{house}(R(i))$ $R = (I - 2vv^T) R$ \[alg:qr:trailing\_update\] $Q = Q (I - 2vv^T)$

SVD Algorithms
--------------

Most implementations of the SVD are based on the two-phase approach popularized by Trefethen et al. [@trefethen1997numerical], where the matrix $A$ first undergoes bidiagonalization of the form $A = Q_U B Q_V^T$ where $Q_U$ and $Q_V$ are orthonormal matrices and $B$ is a bidiagonal matrix. The matrix $B$ is then diagonalized using some variant of the QR algorithm, the divide and conquer method or a 