Skip to content

BLAS: make i?amax return the first NaN, and test all four (full coverage) - #1416

Open
ACSimon33 wants to merge 1 commit into
masterfrom
blas-cov-iamax-nonfinite
Open

ACSimon33 wants to merge 1 commit into
masterfrom
blas-cov-iamax-nonfinite

Conversation

@ACSimon33

Copy link
Copy Markdown
Collaborator

Description

icamax and izamax were rewritten for Demmel et al., Proposed Consistent Exception Handling for the BLAS and LAPACK in #1116, and since then return the index of the first NaN, or failing that the first Inf. isamax and idamax were left on the old IF (ABS(SX(I)) .GT. SMAX) comparison, which is false whenever either side is a NaN, so a NaN is skipped rather than selected. The four routines therefore disagree, and the real pair's answer depends on where in the vector the NaN happens to sit:

Input isamax before icamax isamax after
[0, NaN, 2] 3 2 2
[NaN, 0, 2] 1 1 1
[1, Inf, NaN] 2 3 3

This PR applies the rule to isamax and idamax, states the contract in the Purpose block of all four (it was previously only in inline comments, even on the complex pair), and adds tests.

The change

SMAX = ABS(SX(1))
IF (SMAX.NE.SMAX) RETURN
DO I = 2,N
   IF (.NOT.(ABS(SX(I)).LE.SMAX)) THEN
      ISAMAX = I
      SMAX = ABS(SX(I))
      IF (SMAX.NE.SMAX) RETURN
   END IF
END DO

.NOT.(a .LE. b) is true when a is a NaN and when a > b, so a NaN is taken and then returned. For finite data the result is unchanged, including the tie rule: equal elements still leave the earliest index in place.

Coverage

Measured locally with gfortran 13.3.0: BLAS/SRC built -O0 -g --coverage -fno-inline, the four ?blat1 drivers linked against it and run, then gcov -b -n. Percentages are lines executed and branches taken at least once; the denominators are gcov's, and they grow for the real pair because the change adds code.

Routine Lines before Lines after Branches before Branches after
isamax.f, idamax.f 100% of 20 100% of 24 100% of 14 100% of 22
icamax.f90, izamax.f90 48.39% of 62 100% of 62 52.38% of 42 100% of 42

Benchmark

There is no measurable cost. On gfortran 13.3.0 -O2, x86-64, n = 100000, the new isamax runs at 0.59x to 0.68x of the old across random, ascending and descending data. The old IF (ABS(x) .GT. SMAX) lets gfortran emit an unconditional maxss, which serialises the loop on a loop-carried latency chain; the new form has no maxss and a well-predicted branch instead. Only gfortran on x86-64 was timed.

isamax and idamax skipped NaNs entirely, so the index they returned
depended on where the NaN sat; icamax and izamax have returned the first
one since they were rewritten for arXiv:2207.09281.  Give the real pair
the same rule, document the contract on all four, and test it.

Inf and NaN are built the way ?B1NRM2 in the same testers already builds
them, from HUGE, since a constant expression would be folded and
rejected at compile time.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Sep 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 69.38%. Comparing base (a6c6e74) to head (b358788).
✅ All tests successful. No failed tests found.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1416      +/-   ##
==========================================
+ Coverage   69.36%   69.38%   +0.02%     
==========================================
  Files        6122     6122              
  Lines      486711   486847     +136     
  Branches    23268    23268              
==========================================
+ Hits       337584   337790     +206     
+ Misses     148689   148629      -60     
+ Partials      438      428      -10     
Components Coverage Δ
BLAS 98.46% <100.00%> (+0.52%) ⬆️
CBLAS 96.98% <ø> (ø)
LAPACK 82.38% <ø> (ø)
LAPACKE 2.17% <ø> (ø)
TMGLIB 55.69% <ø> (ø)
BLAS testing 88.42% <100.00%> (+0.08%) ⬆️
CBLAS testing 89.63% <ø> (ø)
LAPACK testing 82.20% <ø> (ø)
LAPACKE testing ∅ <ø> (∅)
Files with missing lines Coverage Δ
BLAS/SRC/icamax.f90 100.00% <ø> (+56.45%) ⬆️
BLAS/SRC/idamax.f 100.00% <100.00%> (ø)
BLAS/SRC/isamax.f 100.00% <100.00%> (ø)
BLAS/SRC/izamax.f90 100.00% <ø> (+56.45%) ⬆️
BLAS/TESTING/cblat1.f 90.09% <100.00%> (+1.31%) ⬆️
BLAS/TESTING/dblat1.f 91.32% <100.00%> (+0.47%) ⬆️
BLAS/TESTING/sblat1.f 92.38% <100.00%> (+0.42%) ⬆️
BLAS/TESTING/zblat1.f 90.09% <100.00%> (+1.31%) ⬆️

Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a6c6e74...b358788. Read the comment docs.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant