efp_regularize Subroutine

public pure subroutine efp_regularize(e)

efp_carry plus: force every bin to share the overall sign, so a single well-conditioned FP accumulation (efp_to_real) can form Sum pr(n)*e(n) without alternating-sign cancellation error. Mirrors MOM6 regularize_ints.

After efp_carry, bins 2..6 satisfy |e(n)| < 2**P. The overall sign is that of the first (most-significant) nonzero bin. A single descending pass then borrows/carries any bin of the opposite sign into [0, 2**P) (or (-2**P, 0]) from its next-more-significant neighbour – exact, since e(n-1)*2**P + e(n) is invariant under (e(n-1) -+ 1, e(n) +- 2**P) – and cascades: a neighbour driven negative/positive by one borrow is itself fixed on the next loop iteration.

Arguments

Type IntentOptional Attributes Name
integer(kind=int64), intent(inout) :: e(EFP_DIGITS)

Calls

proc~~efp_regularize~~CallsGraph proc~efp_regularize efp_regularize proc~efp_carry efp_carry proc~efp_regularize->proc~efp_carry

Called by

proc~~efp_regularize~~CalledByGraph proc~efp_regularize efp_regularize proc~efp_from_transport efp_from_transport proc~efp_from_transport->proc~efp_regularize proc~efp_minus efp_minus proc~efp_minus->proc~efp_regularize proc~efp_plus efp_plus proc~efp_plus->proc~efp_regularize proc~efp_to_real efp_to_real proc~efp_to_real->proc~efp_regularize proc~efp_real_diff efp_real_diff proc~efp_real_diff->proc~efp_minus proc~efp_real_diff->proc~efp_to_real proc~halo_allreduce_efp_list halo_allreduce_efp_list proc~halo_allreduce_efp_list->proc~efp_from_transport proc~ocean_console_stats_report ocean_console_stats_report proc~ocean_console_stats_report->proc~efp_to_real proc~ocean_console_stats_report->proc~halo_allreduce_efp_list proc~console_stats_report console_stats_report proc~ocean_console_stats_report->proc~console_stats_report proc~console_stats_report->proc~efp_real_diff proc~driver_run_ocean driver_run_ocean proc~driver_run_ocean->proc~ocean_console_stats_report proc~driver_run driver_run proc~driver_run->proc~driver_run_ocean

Variables

Type Visibility Attributes Name Initial
integer, private :: n
logical, private :: positive

Source Code

   pure subroutine efp_regularize(e)
      !! `efp_carry` plus: force every bin to share the overall sign, so a
      !! single well-conditioned FP accumulation (`efp_to_real`) can form
      !! `Sum pr(n)*e(n)` without alternating-sign cancellation error.
      !! Mirrors MOM6 `regularize_ints`.
      !!
      !! After `efp_carry`, bins 2..6 satisfy `|e(n)| < 2**P`.  The overall
      !! sign is that of the first (most-significant) nonzero bin.  A
      !! single descending pass then borrows/carries any bin of the
      !! opposite sign into `[0, 2**P)` (or `(-2**P, 0]`) from its
      !! next-more-significant neighbour -- exact, since
      !! `e(n-1)*2**P + e(n)` is invariant under `(e(n-1) -+ 1, e(n) +- 2**P)`
      !! -- and cascades: a neighbour driven negative/positive by one
      !! borrow is itself fixed on the next loop iteration.
      integer(int64), intent(inout) :: e(EFP_DIGITS)
      integer :: n
      logical :: positive

      call efp_carry(e)

      positive = .true.
      do n = 1, EFP_DIGITS
         if (e(n) /= 0_int64) then
            positive = e(n) > 0_int64
            exit
         end if
      end do

      if (positive) then
         do n = EFP_DIGITS, 2, -1
            if (e(n) < 0_int64) then
               e(n) = e(n) + EFP_PREC_I64
               e(n - 1) = e(n - 1) - 1_int64
            end if
         end do
      else
         do n = EFP_DIGITS, 2, -1
            if (e(n) > 0_int64) then
               e(n) = e(n) - EFP_PREC_I64
               e(n - 1) = e(n - 1) + 1_int64
            end if
         end do
      end if
   end subroutine efp_regularize