Skip to content

Commit 2938571

Browse files
Technologicatclaude
andcommitted
Fix GCC may-be-uninitialized warning on k in the iterative scalers
The DEF-removal pass had hoisted `niters = 100` from a compile-time `DEF` (Cython-level literal) to a module-level `cdef int`. Cython emits module-level `cdef int` as a `static int` global, and GCC declines to constant-propagate through a mutable global — so `for k in range(niters)` looked to the C compiler like it might execute zero iterations, and `return k + 1` at the tail of `rescale_ruiz2001_c` / `rescale_scalgm_c` looked like it might read an uninitialized `k`. In practice `niters == 100` always (nothing ever writes to it), so the warning is a false positive at runtime. It is still a real signal that the as-written code permits the read, and the fix is free: restore `niters` as a function-local `cdef int niters = 100` at the top of each iterative scaler. Cython emits that as a stack local, GCC constant- folds trivially, the warning vanishes, and the generated machine code is identical to the DEF-era output. `epsilon` stays at module level; it's a convergence tolerance, not a loop bound, and does not appear in any uninit-read path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent eb92bef commit 2938571

1 file changed

Lines changed: 9 additions & 3 deletions

File tree

wlsqm/utils/lapackdrivers.pyx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,12 @@ from scipy.linalg.cython_lapack cimport dgesv, dgetrf, dgetrs
7979
# other routines
8080
from scipy.linalg.cython_lapack cimport dgeequ, dgesvd
8181

82-
# Module-level C constants used by the iterative scaler (rescale_ruiz2001_c,
83-
# rescale_scalgm_c), replacing old compile-time `DEF` constants.
82+
# Module-level C constant replacing the old compile-time `DEF epsilon`:
83+
# stopping tolerance shared by both iterative scalers. (The per-function
84+
# iteration bound `niters` is kept as a function-local cdef — otherwise GCC
85+
# cannot prove the `for k in range(niters)` loop body ever runs and warns
86+
# that the `return k + 1` at the tail may read an uninitialized `k`.)
8487
cdef double epsilon = 1e-15 # stopping tolerance at double precision
85-
cdef int niters = 100 # maximum number of iterations
8688

8789
# fast inline min/max for C code
8890
#
@@ -549,6 +551,8 @@ Reference:
549551
return do_rescale( A, ScalingAlgo.ALGO_RUIZ2001 )
550552

551553
cdef int rescale_ruiz2001_c( double* A, int nrows, int ncols, double* row_scale, double* col_scale ) noexcept nogil:
554+
cdef int niters = 100 # maximum number of refinement iterations — function-local so GCC can constant-fold it through the loop bound
555+
552556
# temporary work space
553557
cdef double* DR = <double*>malloc( nrows*sizeof(double) )
554558
cdef double* DC = <double*>malloc( ncols*sizeof(double) )
@@ -739,6 +743,8 @@ cdef void basic_scale_down_cols( double* A, int nrows, int ncols, double* rs, do
739743

740744
# SCALGM driver
741745
cdef int rescale_scalgm_c( double* A, int nrows, int ncols, double* row_scale, double* col_scale ) noexcept nogil:
746+
cdef int niters = 100 # maximum number of refinement iterations — function-local so GCC can constant-fold it through the loop bound
747+
742748
# temporary work space
743749
cdef double* DR1 = <double*>malloc( nrows*sizeof(double) )
744750
cdef double* DC1 = <double*>malloc( ncols*sizeof(double) )

0 commit comments

Comments
 (0)