Inverse of efp_to_transport: unpack a flat
real64(EFP_TRANSPORT_WIDTH*n) buffer (post-collective, still
exact integers as doubles) back into efp_t values, converting
each bin AND the summed poison counter back to int64 and
carrying the bins. ok = .false. iff any unpacked double is not
an exact integer (would indicate the transport-exactness bound
was violated) – the caller (halo_allreduce_efp_list) turns that
into a fail-loud error stop, never a silent truncation.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=real64), | intent(in) | :: | buf(:) | |||
| type(efp_t), | intent(out) | :: | list(:) | |||
| logical, | intent(out) | :: | ok |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | private | :: | i | ||||
| integer, | private | :: | n | ||||
| real(kind=real64), | private | :: | val |
pure subroutine efp_from_transport(buf, list, ok) !! Inverse of `efp_to_transport`: unpack a flat !! `real64(EFP_TRANSPORT_WIDTH*n)` buffer (post-collective, still !! exact integers as doubles) back into `efp_t` values, converting !! each bin AND the summed `poison` counter back to `int64` and !! carrying the bins. `ok = .false.` iff any unpacked double is not !! an exact integer (would indicate the transport-exactness bound !! was violated) -- the caller (`halo_allreduce_efp_list`) turns that !! into a fail-loud `error stop`, never a silent truncation. real(real64), intent(in) :: buf(:) type(efp_t), intent(out) :: list(:) logical, intent(out) :: ok integer :: i, n real(real64) :: val ok = .true. do i = 1, size(list) do n = 1, EFP_DIGITS val = buf((i - 1)*EFP_TRANSPORT_WIDTH + n) if (val /= aint(val)) ok = .false. list(i)%v(n) = int(val, int64) end do val = buf((i - 1)*EFP_TRANSPORT_WIDTH + EFP_DIGITS + 1) if (val /= aint(val)) ok = .false. list(i)%poison = int(val, int64) ! Regularise (not merely carry) so the post-combine bins are the ! SAME canonical representation a single-rank EFP sum of the ! whole field would produce -- see `efp_plus`'s docstring for why ! carry alone is not bit-for-bit order-invariant. Harmless (and ! still needed for the transport-exactness `ok` semantics) even ! when `poison /= 0`, since `efp_to_real` never reads `v(:)` in ! that case. call efp_regularize(list(i)%v) end do end subroutine efp_from_transport