efp_t Derived Type

type, public :: efp_t

An order-invariant fixed-point value: Sum_n v(n) * pr(n). The component is PUBLIC (unlike MOM6’s private EFP_type%v) so the comm facade (halo_allreduce_efp_list) can pack/unpack it without an accessor procedure – Roundabout splits the arithmetic module (here) from the collective (in src/comm/), so the layering requires v to be reachable from both. Tests asserting bit- identity compare v(:) directly, never the reconstructed real.


Inherited by

type~~efp_t~~InheritedByGraph type~efp_t efp_t type~console_stats_t console_stats_t type~console_stats_t->type~efp_t mass0_efp, salt0_efp, heat0_efp

Components

Type Visibility Attributes Name Initial
integer(kind=int64), public :: poison = 0_int64

Non-finite “poison” counter – the number of NaN / +-Inf / bin-1-overflow summands folded into this value so far (0 = clean). efp_decompose/efp_from_real seed it from is_nan .or. is_ovf; efp_plus/efp_minus add it forward (never reset it); efp_to_real returns a quiet NaN whenever it is nonzero, INSTEAD OF reconstructing a value from v(:). This is the fix for the EFP fixed-point path laundering a non-finite summand into a plausible finite number (0 comes out of a NaN decompose’s zeroed bins, a saturated bin 1 comes out of an overflowing one) – the exact hazard class CLAUDE.md’s NaN-blind-clamp gotcha describes, just in the reduction layer instead of a clamp. efp_to_transport/efp_from_transport carry it in the SAME collective as the bins (see EFP_TRANSPORT_WIDTH), summed by the same MPI_SUM: one poisoned rank makes the transported count nonzero on every rank, so every rank’s efp_to_real reports NaN identically – never a rank-dependent branch. A plain count (not a saturating flag) because it costs nothing extra (still an exact double under MPI_SUM at any realistic magnitude) and is simpler to reason about than a boolean OR chain.

integer(kind=int64), public :: v(EFP_DIGITS) = 0_int64

Source Code

   type :: efp_t
      !! An order-invariant fixed-point value: `Sum_n v(n) * pr(n)`.  The
      !! component is PUBLIC (unlike MOM6's private `EFP_type%v`) so the
      !! comm facade (`halo_allreduce_efp_list`) can pack/unpack it without
      !! an accessor procedure -- Roundabout splits the arithmetic module
      !! (here) from the collective (in `src/comm/`), so the layering
      !! requires `v` to be reachable from both.  Tests asserting bit-
      !! identity compare `v(:)` directly, never the reconstructed real.
      integer(int64) :: v(EFP_DIGITS) = 0_int64
      integer(int64) :: poison = 0_int64
         !! Non-finite "poison" counter -- the number of NaN / +-Inf /
         !! bin-1-overflow summands folded into this value so far (0 =
         !! clean). `efp_decompose`/`efp_from_real` seed it from `is_nan
         !! .or. is_ovf`; `efp_plus`/`efp_minus` add it forward (never
         !! reset it); `efp_to_real` returns a quiet NaN whenever it is
         !! nonzero, INSTEAD OF reconstructing a value from `v(:)`.  This
         !! is the fix for the EFP fixed-point path laundering a non-finite
         !! summand into a plausible finite number (0 comes out of a NaN
         !! decompose's zeroed bins, a saturated bin 1 comes out of an
         !! overflowing one) -- the exact hazard class CLAUDE.md's
         !! NaN-blind-clamp gotcha describes, just in the reduction layer
         !! instead of a clamp. `efp_to_transport`/`efp_from_transport`
         !! carry it in the SAME collective as the bins (see
         !! `EFP_TRANSPORT_WIDTH`), summed by the same `MPI_SUM`: one
         !! poisoned rank makes the transported count nonzero on every
         !! rank, so every rank's `efp_to_real` reports NaN identically --
         !! never a rank-dependent branch. A plain count (not a saturating
         !! flag) because it costs nothing extra (still an exact double
         !! under `MPI_SUM` at any realistic magnitude) and is simpler to
         !! reason about than a boolean OR chain.
   end type efp_t