!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module cubetools_extrema_types
  use cubetools_parameters
  use cubetools_nan
  use cubetools_header_types
  use cubetools_arrelt_types
  !---------------------------------------------------------------------
  ! Support module for a dedicated type used in the context of extrema
  ! computation. As the extrema are updated at entry%put() time, there
  ! can be a race condition between tasks.
  !---------------------------------------------------------------------
  !
  type :: cubetools_extrema_t
    type(arrelt_t)       :: min   ! Minimum value
    type(arrelt_t)       :: max   ! Maximum value
    integer(kind=data_k) :: nnan  ! Number of NaN elements
  contains
    procedure, public :: init  => cubetools_extrema_init
    procedure, public :: merge => cubetools_extrema_merge
  end type cubetools_extrema_t
  !
  public :: cubetools_extrema_t
  private
  !
contains
  !
  subroutine cubetools_extrema_init(ext,head,error)
    !-------------------------------------------------------------------
    !
    !-------------------------------------------------------------------
    class(cubetools_extrema_t), intent(out)   :: ext
    type(cube_header_t),        intent(in)    :: head
    logical,                    intent(inout) :: error
    !
    call cubetools_arrelt_init('Min',ext%min,error)
    if (error)  return
    call cubetools_arrelt_init('Max',ext%max,error)
    if (error)  return
    ! Ensure min%ix min%iy min%ic pointers are properly set
    call ext%min%associate(head%set%il,head%set%im,head%set%ic,error)
    if (error)  return
    call ext%max%associate(head%set%il,head%set%im,head%set%ic,error)
    if (error)  return
    !
    ext%nnan    = 0
  end subroutine cubetools_extrema_init
  !
  subroutine cubetools_extrema_merge(out,ouhead,in,error)
    !-------------------------------------------------------------------
    ! Merge a list of cubetools_extrema_t into a single one
    !-------------------------------------------------------------------
    class(cubetools_extrema_t), intent(out)   :: out
    type(cube_header_t),        intent(in)    :: ouhead
    type(cubetools_extrema_t),  intent(in)    :: in(:)
    logical,                    intent(inout) :: error
    !
    integer(kind=4) :: iext
    !
    call out%init(ouhead,error)
    !
    do iext=1,size(in)
      if (ieee_is_nan(out%min%val) .or. in(iext)%min%val.lt.out%min%val) then
        out%min = in(iext)%min
      endif
      if (ieee_is_nan(out%max%val) .or. in(iext)%max%val.gt.out%max%val) then
        out%max = in(iext)%max
      endif
      out%nnan = out%nnan + in(iext)%nnan
    enddo
  end subroutine cubetools_extrema_merge
  !
end module cubetools_extrema_types
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
