Re-derives the frozen transform over 32 fixed inputs and compares against ek_contract_fp.
Why a run-time check for a compile-time property. The barriers now cover every build this project can test, fast-math included, so this check is expected to pass everywhere -- which is exactly why it must stay. It is the only thing that would report a compiler, a version or a flag nobody has swept doing something no barrier anticipated. A build that diverges produces a DIFFERENT permutation from every other build, silently, and a weighted permutation is decided by the ORDER of the keys, so one differing key changes which items are drawn.
It has already earned its place once. Before the final sum was barriered, a bare
fpm build/fpm test under ifx -- which passes no fp-model flag, so ifx takes its own
-O2 and -fp-model=fast defaults -- produced exactly that divergence, and this check is
what reported it instead of letting the permutations quietly disagree.
Costs 32 exp_key calls, some hundreds of nanoseconds, against a permutation that is at
best O(n log n). That is cheap enough to run on every call rather than caching in a saved
flag -- which would need thread-safety reasoning to save nothing worth saving.
What this canNOT do, because 32 inputs is a sparse sample. It catches a build that has
left IEEE semantics wholesale, which is what it is for and what the wording above describes.
It does NOT reliably catch a barrier that has gone missing: measured on machine C, the
former noinline barrier was lost entirely under flang -O3 -march=native, and this check
still reproduced ek_contract_fp exactly, because the divergence touched 4 of the 13824
inputs tools/check_exp_key.sh sweeps and none of the 32 sampled here (this check varies
only 8 distinct mantissas). So do not cite it as a second line of defence for the barrier --
the script is what found that, and the script is what would find the next one.
logical function exp_key_contract_ok() integer(int64) :: fp real(real64) :: u integer :: k fp = 0_int64 do k = 0, 31 u = scale(0.5_real64 + real(mod(k * 5, 8), real64) / 16.0_real64, -k) fp = ieor(fp, transfer(exp_key(u), 0_int64)) fp = fp_step(fp) end do exp_key_contract_ok = fp == ek_contract_fp .and. .not. ek_dbg_force_fail end function exp_key_contract_ok