…f scaling by its reciprocal
xGBTF2 and xGBTRF form the multipliers of column J as
CALL xSCAL( KM, ONE / AB( KV+1, J ), AB( KV+2, J ), 1 )
When the pivot is subnormal its reciprocal is not representable, so the
whole column of L becomes Inf, or NaN where an entry is zero, the xGER
update spreads that through the band, and the factorization completes
with INFO = 0. Partial pivoting cannot avoid it: the pivot is the
largest entry of the column, and when the matrix is small every column
is. A well-conditioned banded system scaled to 2^-1030 is solved by
xGESV to 1e-14 and by xGBSV to NaN.
The dense routines xGETF2 and xGETRF2 have guarded this since at least
LAPACK 3.2 by dividing element-wise when |pivot| < SFMIN. Apply the
same test at both banded sites, in all four precisions. SFMIN comes
from xLAMCH('S'), computed once after the quick return as in xGETF2.
The GB test path gets a matrix type for it: type 9 is the type 1
matrix scaled into the subnormal range, one eighth of the safe minimum,
which xLATMS cannot generate because it scales its output to the
requested norm. At that scale the matrix carries too few bits to
reconstruct, so the type tests what the guarded division promises, that
the factor is finite, instead of a residual; the remaining ratios,
which estimate a condition number from a subnormal norm, are skipped as
for a block size other than the first. On the parent commit the type
fails 798 times per precision.
The new branch is taken only when |pivot| < SFMIN. Over a sweep of
2124 (precision, n, KL, KU, scale) cases the banded factor and IPIV are
bit-identical to the parent commit for every pivot of normal magnitude,
and for the subnormal cases the banded solution error now equals the
dense one in every case, where before 560 of 708 came back NaN or Inf.
The full LAPACK test suite passes: 5447193 LAPACK and 315872 BLAS
tests, 0 numerical errors, 0 other errors; the 5292 tests above the
parent are the new type.
The test files declare the new xSCAL calls EXTERNAL: the extended-API
build renames only the routines a file declares, so without the
declaration the xlintst*_64 executables failed to link against the
64-bit BLAS.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Disclaimer: This PR was prepared using Claude Code.
Summary
The banded LU factorizations
xGBTF2andxGBTRF(all eight:S/D/C/Z× unblocked/blocked) form the multipliers of columnJasxSCAL( KM, ONE / pivot, ... ). When the pivot is subnormal,ONE / pivotoverflows toInf, the column ofLbecomesInf/NaN, and the factorization completes withINFO = 0.xGBSVthen returns aNaNsolution as success for a system that is perfectly well conditioned. The dense LU (xGETF2,xGETRF2) has guarded this since at least LAPACK 3.2 (it is present in the 2008 import of the trunk) by dividing element-wise when|pivot| < SFMIN; this PR adds the same guard to the banded routines. Nothing changes for a pivot of normal magnitude.Description
xGETF2computes the column of multipliers asand
xGETRF2the same at the base of its recursion. The banded routines have only the first branch:For a pivot below
2^-1022(double) the reciprocal is not representable, so every multiplier in the column isInf, orNaNwhere the entry is zero; thexGERtrailing update then spreads that through the rest of the band. Partial pivoting does not help: it picks the largest entry of the column, and when the whole matrix is small every column is.xGTTRFandxGETC2are unaffected because they divide. The tridiagonal driverxGTSVand the dense driverxGESVboth solve the reproducer below to full accuracy.Fix. The
xGETF2form at both sites: keep the reciprocal scaling when|pivot| >= SFMIN, divide element-wise otherwise. Eight files.SFMIN = xLAMCH('S')is computed once after the quick return, as inxGETF2; neither banded routine referencedxLAMCHbefore.Minimal reproducer
A banded, diagonally dominant matrix with every entry near
2^-1030;b = A * ones, so the exact solution is the vector of ones.Validation
Band versus dense sweep, 2124 cases per build
xGBSVagainstxGESVon the same non-symmetric, diagonally dominant banded matrix withb = A * ones: four precisions,nin {1, 2, 3, 5, 8, 13, 40, 64, 130},KLandKUeach in {0, 1, 2, 3, 5, 40} (so both the unblockedxGBTF2path and, forKL = 40 >= NB, the blockedxGBTRFpath), and three scalings: normal (s = 1), subnormal (s = 2^-1030in double,2^-140in single), and near the overflow threshold (s = huge/64). Each line recordsINFOandmax|x - 1|for both drivers plus FNV-1a hashes of the banded factor andIPIV.< 1e-3, master< 1e-3, this branch< 1e-3NaN/Inf, masterNaN/Inf, this branchOn master, 560 of the 708 subnormal cases come back
NaNorInfwithINFO = 0; the 148 that survive haveKL = 0orn = 1, where there is no multiplier to scale. On this branch the banded error equals the dense error in every case (the largest ratioerr_band / err_denseover all finite pairs is 1.00 in all four precisions), andINFOagrees with the dense driver in 708 of 708. The 54 subnormal cases where both drivers exceed1e-3are all single precision: at2^-140aREALcarries about 9 significant bits, so that is the input, not the solver.For the normal and near-max scalings all 1416 lines, hashes included, are byte-identical between master and this branch: the new branch is reached only when
|pivot| < SFMIN.Regression test. The
?GBpath gets a matrix type 9: the type 1 matrix scaled in place into the subnormal range, one eighth of the safe minimum, which is below the reciprocal of the overflow threshold in every precision.xLATMScannot generate such a matrix, since it scales its output to the requested norm, and it returns Inf or NaN entries for a subnormalANORMon the shapes that go through its Givens chase.At that scale the stored matrix carries too few bits for a reconstruction residual to mean anything: in single precision an entry near 2^-134 keeps about fifteen, and the ratio of a correct factorization lands near 300. The type therefore checks what the guarded division promises, that the factor is finite, through the max-norm of the factor rather than
xGBT01. The condition-number and solve ratios, which would form the reciprocal of a subnormal norm, are skipped for it as they already are for a block size other than the first.On the parent commit the type fails 798 times per precision, one for each shape and block size, with the factor holding an infinity; with the fix all four precisions pass.
Test suite. The full LAPACK test suite passes on this branch: 215 of 215 CTest entries, 5447193 LAPACK tests and 315872 BLAS tests with 0 numerical errors and 0 other errors, built and run the same way as the parent commit
f96546fc9. That includes the?GBroutine and driver families (DGB: 30261 routine tests, 36567 driver tests) and the_64extended-API variants. Built with GCC 13.3,CMAKE_BUILD_TYPE=Release,BUILD_INDEX64_EXT_API=ON.Checklist