Skip to content

Retain nonzero columns in unpivoted QR (fixes #28-style column loss) - #1

Merged
shinaoka merged 2 commits into
mainfrom
qr-skip-fix
Oct 8, 2026
Merged

shinaoka merged 2 commits into
mainfrom
qr-skip-fix

Conversation

@shinaoka

@shinaoka shinaoka commented Oct 8, 2026

Copy link
Copy Markdown
Member

faer's unpivoted Householder QR treats a column as zero when its part orthogonal to the previous columns is below 16*(m-row)*eps*||column||, then skips both the reflector and the row advance, so the column is lost from Q and R. LAPACK has no such skip.

Reproduced with the matrix from tensor4all/tlinalg-rs#28, A = [a, a + 1e-10 e_0, a + 1e-6 e_1] with a = (1,...,1), column-major m x 3:

m before after
100 (control) 1.463e-16 1.463e-16
1000 2.580e-12 1.982e-15
8192 9.004e-13 4.590e-15

(||A - QR|| / ||A||.) The change is the condition: apply the reflector and advance the row whenever the column is not exactly zero, keeping the blocked structure, the trailing update, the tau convention and the min_positive() shortcut. A release smoke showed no measurable cost on 100000 x 8 (2.984 → 2.986 ms) or 1000 x 1000 (19.79 → 19.92 ms), 3-run means.

cargo test -p t4a-faer: 232 passed, 2 ignored. The fork's ledger PATCHSET.md records the experiment as kept, with the test and the issues it serves (tlinalg-rs#28, tensor4all-rs#836).

The unpivoted QR column skip lived only in `qr_in_place_unblocked`.
`qr_in_place_blocked` has no threshold of its own and recurses into that
core, so removing the threshold there already covers the wide path; there is
no wide-specific branch. Add the transposed fixture as a wide `3 x n`
regression test (n = 100/1000/8192).

That wide fixture reconstructs to ~4e-16 both with and without the change:
at m = 3 the removed threshold `16 (m-k) eps ||column||` is ~1e-14 and never
tripped. The tall m = 1000 case goes 2.58e-12 -> 1.98e-15.

tlinalg's reported wide `3.33e-7` for this fixture is a reconstruction-
indexing bug in that test: it writes entry (i, j) to flat `j + 3i` while the
column-major factor uses `i + 3j`. faer's factors for the matrix are accurate
to ~4e-16 under the correct indexing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant