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.
Nodes of different colours represent the following:
Solid arrows point from a procedure to one which it calls. Dashed
arrows point from an interface to procedures which implement that interface.
This could include the module procedures in a generic interface or the
implementation in a submodule of an interface in a parent module.
Where possible, edges connecting nodes are
given different colours to make them easier to distinguish in
large graphs.
Nodes of different colours represent the following:
Solid arrows point from a procedure to one which it calls. Dashed
arrows point from an interface to procedures which implement that interface.
This could include the module procedures in a generic interface or the
implementation in a submodule of an interface in a parent module.
Where possible, edges connecting nodes are
given different colours to make them easier to distinguish in
large graphs.
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::nlogical::positivecall efp_carry(e)positive=.true.do n=1,EFP_DIGITSif(e(n)/=0_int64)thenpositive=e(n)>0_int64exit end if end do if(positive)then do n=EFP_DIGITS,2,-1if(e(n)<0_int64)thene(n)=e(n)+EFP_PREC_I64e(n-1)=e(n-1)-1_int64end if end do else do n=EFP_DIGITS,2,-1if(e(n)>0_int64)thene(n)=e(n)-EFP_PREC_I64e(n-1)=e(n-1)+1_int64end if end do end if end subroutine efp_regularize