@@ -151,11 +151,13 @@ def _has_converged(s, s_old, tol=1e-6):
151151 bool
152152 True if FISTA has converged, False otherwise
153153 """
154- # Calculate normalized error between current and previous estimate
155- estimate_error = jnp .abs (s - s_old ) / jnp .abs (s_old )
154+ # Normalized change between iterates. Guard the denominator against the
155+ # zeros that sparsity produces: 0 -> 0 reads as converged, 0 -> nonzero as a
156+ # real change (a bare |s_old| denominator yields NaN/inf and blocks stopping).
157+ estimate_error = jnp .abs (s - s_old ) / jnp .maximum (jnp .abs (s_old ), 1e-10 )
156158
157159 # Check if the error is smaller than the tolerance for all voxels
158- return jnp .all (jnp . abs ( estimate_error ) <= tol ).astype (jnp .bool_ )
160+ return jnp .all (estimate_error <= tol ).astype (jnp .bool_ )
159161
160162
161163def fista (
@@ -375,8 +377,9 @@ def fista(
375377
376378 t_fista , y_fista_s = _fista_update_jit (t_fista , s , s_old )
377379
378- # Convergence
379- if num_iter >= min_iter and _has_converged_jit (s_old , s , tol ).block_until_ready ():
380+ # Convergence. Pass (current, previous) so _has_converged normalizes
381+ # the change by |s_old| as documented (the args were previously swapped).
382+ if num_iter >= min_iter and _has_converged_jit (s , s_old , tol ).block_until_ready ():
380383 break
381384
382385 LGR .debug (f"Iteration: { str (num_iter )} / { str (max_iter )} " )
0 commit comments