-| **Won't-fix — not bit-identically achievable (verified 2026-06-01).** The proposed `bread_inv` reuse / "factor `(X'WX)` once, reuse across HC2/HC2-BM" cannot be done **bit-identically**, which is the bar for a pure perf refactor of the inference path (no SE may move at all). The internal bread operations solve against *different* right-hand sides (`X.T` for hat-diagonals, `eye` for classical/CR2, `meat`+`temp.T` for the sandwich, `contrasts` for BM-DOF); only **same-RHS** results are bit-reusable. Measured (numpy 2.4.5): `scipy.linalg.lu_solve(lu_factor(A), B)` differs from `np.linalg.solve(A, B)` by up to 6.4e-15 (only 32/900 bit-equal — `dgesv` fuses factor+solve and rounds differently from a separate `dgetrf`+`dgetrs`); the `inv(A) @ meat @ inv(A)` sandwich differs from the current double-`solve` by up to 1.24e-14. Both are **nonzero → not bit-identical** — and note both sit *below* the affected goldens' actual tolerances (the HC2/HC2-BM/CR2 asserts are atol 1e-12/1e-10, e.g. `test_methodology_wls_cr2.py::TestUnweightedRegressionStillBitEqual` at 1e-12; the atol=1e-14 checks in `test_linalg_hc2_bm.py` are HC1 default-vs-explicit *dispatch*-equality sentinels, not this path), so a broad reuse would silently shift SEs at ~1e-14 *without* tripping the suite, which is exactly what the bit-identity bar exists to prevent. `np.linalg.solve(A, eye) == np.linalg.inv(A)` IS bit-identical (and raises the same `LinAlgError`) but swapping saves nothing. The *only* genuine bit-identical redundancy is one duplicated `solve(bread, X.T)` (hat-diagonals + the DOF `H`-build) in the unweighted one-way `hc2_bm`+`return_dof` path — an O(k²n) solve dwarfed by the O(n²) `M=I−H` build and the O(G²·n²) per-coefficient DOF loop, so the achievable saving is negligible. | `linalg.py::compute_robust_vcov` | Phase 1a | Low |
0 commit comments