**Practical considerations.** Since the matrix \(\mathbf{Q}\) is not computed over the reals, but over floating-point numbers (possibly with precision as low as 16-bits or 8-bits for production neural networks), we cannot naively take the rank to be the number of linearly independent rows. Instead, we use a practical _numerical rank_ of \(\mathbf{Q}\), where we order the singular values \(\lambda_{1}\geq\lambda_{2}\geq\cdots\geq\lambda_{n}\), and identify the largest _multiplicative_ gap \(\frac{\lambda_{1}}{i+1}\) between consecutive singular values. A large multiplicative gap arises when we switch from large "actual" singular values to small singular values that arise from numerical imprecision. Figure 2 shows these gaps. Algorithm 1 describes this attack.