Templatize SVD on N: support any Matrix<R,C> with stack-only buffers
Replace the fixed 5x5 SVD implementation with template <uint8_t N> building blocks over Matrix<N,N> working buffers (N = max(rows, cols)), removing the 5x5 size limit. Public API (SVD::SVD) is unchanged and the whole path stays heap-free: peak stack is ~11*N^2 floats, budgeted in the SVD.hpp header doc. Fixes found while porting/validating the templated rewrite: - QL.Identity() was a no-op (static factory returns by value); init the Householder accumulators with an explicit diagonal loop - restore the QL column sign-flip in ExtractAndSortSingularValues for negative unsolved W diagonal entries (Householder sign flips) - T = B^T B tridiagonal formula: T[i][i] = d[i]^2 + e[i-1]^2 only (e[i] contributes to T[i+1][i+1], not T[i][i]) - wide-matrix Vt assembly: Vt = QL^T must be filled over the full m x m (m = columns of A), not just the top n x n Tests: - matrix-tests: add large-size instantiation cases beyond the old limit (tall 7x5 N=7, square 6x6 N=6, wide 5x8 N=8 transpose path with full orthogonal 8x8 Vt, tall 6x4 near rank-deficient N=6 deflation path), all checked against numpy/scipy float32 references - svd-build-blocks-tests: adapt Jacobi test to the Matrix<N,N> interface - svd-reference-values.py: add the four new reference matrices
This commit is contained in:
@@ -401,6 +401,37 @@ def main():
|
||||
("Zero 3x3", np.zeros((3,3))),
|
||||
("Col vector 2x1", np.array([[3],[4]], dtype=np.float64)),
|
||||
("Row vector 1x2", np.array([[3,4]], dtype=np.float64)),
|
||||
# Large-size instantiation cases (N > 5). Literals MUST match the
|
||||
# C++ test matrices in unit-tests/matrix-tests.cpp exactly, and the
|
||||
# C++ references use float32 inputs: cast to float32 before svd().
|
||||
("Tall 7x5", np.array([
|
||||
[-0.7528, 2.7043, 1.392, 0.592, -2.0639],
|
||||
[-2.064, -2.6515, 2.1971, 0.6067, 1.2484],
|
||||
[-2.8765, 2.8195, 1.9947, -1.726, -1.9091],
|
||||
[-1.8996, -1.1745, 0.1485, -0.4083, -1.2526],
|
||||
[0.6711, -2.163, -1.2471, -0.8018, -0.2636],
|
||||
[1.7111, -1.802, 0.0854, 0.5545, -2.7213],
|
||||
[0.6453, -1.9769, -2.6097, 2.6933, 2.7938]], dtype=np.float32)),
|
||||
("Square 6x6", np.array([
|
||||
[1.2336, -0.7815, -1.6093, 0.7369, -0.2394, -1.5118],
|
||||
[-0.0193, -1.8624, 1.6373, -0.9649, 0.6501, -0.7532],
|
||||
[0.0803, 0.1868, -1.2606, 1.8783, 1.1005, 1.758],
|
||||
[1.5793, 0.3916, 1.6875, -1.646, -1.2161, -1.8191],
|
||||
[-0.6987, -0.4453, -0.9146, 1.315, -0.573, -0.8763],
|
||||
[0.1708, -1.4363, 1.2088, -1.7018, 1.089, 1.9475]], dtype=np.float32)),
|
||||
("Wide 5x8", np.array([
|
||||
[-1.5064, -2.4724, 1.5773, 1.0343, 1.145, 1.3564, -2.1298, -0.7077],
|
||||
[-1.9207, 1.8155, 0.6165, -0.8455, -2.1822, -0.9451, -0.8741, 1.148],
|
||||
[0.6878, 1.9361, -0.1389, -1.902, 1.0662, 1.3039, 0.3064, 1.3548],
|
||||
[-0.031, 0.1137, -0.3623, -2.3729, -1.9605, -2.3429, 0.6821, -0.9282],
|
||||
[0.0429, 2.0378, -1.2535, -0.4481, 1.2778, -1.356, -2.1151, -1.0512]], dtype=np.float32)),
|
||||
("Tall 6x4 rank-def", np.array([
|
||||
[-0.086904, 1.410225, 1.308323, 2.234762],
|
||||
[0.022123, 0.896751, 0.324176, 0.773607],
|
||||
[-0.473015, 1.555111, 0.290059, 1.157726],
|
||||
[-0.78371, 1.398884, -1.930606, -1.548717],
|
||||
[0.201518, -0.626835, 0.976596, 0.875294],
|
||||
[-1.24206, 1.60595, -3.078089, -2.73695]], dtype=np.float32)),
|
||||
]
|
||||
|
||||
for name, A in test_matrices:
|
||||
|
||||
Reference in New Issue
Block a user