module gmath_interfaces_public
  interface
    function gag_bessel_in(n,x)
      !-----------------------------------------------------------------------
      ! @ public
      ! This subroutine calculates the first kind modified Bessel function
      ! of integer order N, for any REAL X. We use here the classical
      ! recursion formula, when X > N. For X < N, the Miller's algorithm
      ! is used to avoid overflows.
      !
      !     REFERENCE:
      !     C.W.CLENSHAW, CHEBYSHEV SERIES FOR MATHEMATICAL FUNCTIONS,
      !     MATHEMATICAL TABLES, VOL.5, 1962.
      !-----------------------------------------------------------------------
      real(kind=8) :: gag_bessel_in
      integer(kind=4), intent(in) :: n
      real(kind=8),    intent(in) :: x
    end function gag_bessel_in
  end interface
  !
  interface
    function gag_bessel_i0(x)
      !---------------------------------------------------------------------
      ! @ public
      ! Bessel functions for N=0
      !---------------------------------------------------------------------
      real(kind=8) :: gag_bessel_i0
      real(kind=8), intent(in) :: x
    end function gag_bessel_i0
  end interface
  !
  interface
    function gag_bessel_i1(x)
      !---------------------------------------------------------------------
      ! @ public
      ! Bessel functions for N=1
      !---------------------------------------------------------------------
      real(kind=8) :: gag_bessel_i1
      real(kind=8), intent(in) :: x
    end function gag_bessel_i1
  end interface
  !
  interface gag_diff_elem
    subroutine gag_diff_char(caller,secname,secwarned,elemname,a,b)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic gag_diff_elem
      ! Returns a message if the two elements a and b differ.
      ! If the elements are part of a larger section (name section), a
      ! warning about the section is also issued if not yet done.
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: caller
      character(len=*), intent(in)    :: secname
      logical,          intent(inout) :: secwarned
      character(len=*), intent(in)    :: elemname
      character(len=*), intent(in)    :: a,b
    end subroutine gag_diff_char
    subroutine gag_diff_inte(caller,secname,secwarned,elemname,a,b)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic gag_diff_elem
      ! Returns a message if the two elements a and b differ.
      ! If the elements are part of a larger section (name section), a
      ! warning about the section is also issued if not yet done.
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: caller
      character(len=*), intent(in)    :: secname
      logical,          intent(inout) :: secwarned
      character(len=*), intent(in)    :: elemname
      integer(kind=4),  intent(in)    :: a,b
    end subroutine gag_diff_inte
    subroutine gag_diff_long(caller,secname,secwarned,elemname,a,b)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic gag_diff_elem
      ! Returns a message if the two elements a and b differ.
      ! If the elements are part of a larger section (name section), a
      ! warning about the section is also issued if not yet done.
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: caller
      character(len=*), intent(in)    :: secname
      logical,          intent(inout) :: secwarned
      character(len=*), intent(in)    :: elemname
      integer(kind=8),  intent(in)    :: a,b
    end subroutine gag_diff_long
    subroutine gag_diff_real(caller,secname,secwarned,elemname,a,b)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic gag_diff_elem
      ! Returns a message if the two elements a and b differ (with some
      ! machine tolerance).
      ! If the elements are part of a larger section (name section), a
      ! warning about the section is also issued if not yet done.
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: caller
      character(len=*), intent(in)    :: secname
      logical,          intent(inout) :: secwarned
      character(len=*), intent(in)    :: elemname
      real(kind=4),     intent(in)    :: a,b
    end subroutine gag_diff_real
    subroutine gag_diff_dble(caller,secname,secwarned,elemname,a,b)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic gag_diff_elem
      ! Returns a message if the two elements a and b differ (with some
      ! machine tolerance).
      ! If the elements are part of a larger section (name section), a
      ! warning about the section is also issued if not yet done.
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: caller
      character(len=*), intent(in)    :: secname
      logical,          intent(inout) :: secwarned
      character(len=*), intent(in)    :: elemname
      real(kind=8),     intent(in)    :: a,b
    end subroutine gag_diff_dble
  end interface gag_diff_elem
  !
  interface nearly_equal
    function nearly_equal_r4_0d(a,b,eps)
      !---------------------------------------------------------------------
      ! @ public-generic nearly_equal
      !---------------------------------------------------------------------
      logical :: nearly_equal_r4_0d
      real(kind=4), intent(in) :: a,b
      real(kind=4), intent(in) :: eps  ! Acceptable relative difference
    end function nearly_equal_r4_0d
    function nearly_equal_r8_0d(a,b,eps)
      !---------------------------------------------------------------------
      ! @ public-generic nearly_equal
      !---------------------------------------------------------------------
      logical :: nearly_equal_r8_0d
      real(kind=8), intent(in) :: a,b
      real(kind=8), intent(in) :: eps  ! Acceptable relative difference
    end function nearly_equal_r8_0d
    function nearly_equal_r4_1d(a,b,ndata,eps)
      use gildas_def
      !---------------------------------------------------------------------
      ! @ public-generic nearly_equal
      !---------------------------------------------------------------------
      logical :: nearly_equal_r4_1d
      integer(kind=size_length), intent(in) :: ndata
      real(kind=4),              intent(in) :: a(ndata),b(ndata)
      real(kind=4),              intent(in) :: eps  ! Acceptable relative difference
    end function nearly_equal_r4_1d
  end interface nearly_equal
  !
  interface
    function eclass_inte_eq(a,b)
      !---------------------------------------------------------------------
      ! @ public
      ! Equality routine between two integers
      !---------------------------------------------------------------------
      logical :: eclass_inte_eq
      integer(kind=4), intent(in) :: a
      integer(kind=4), intent(in) :: b
    end function eclass_inte_eq
  end interface
  !
  interface
    function eclass_2inte_eq(i1,i2,j1,j2)
      !---------------------------------------------------------------------
      ! @ public
      ! Equality routine between two pairs of integers
      !---------------------------------------------------------------------
      logical :: eclass_2inte_eq
      integer(kind=4), intent(in) :: i1,i2
      integer(kind=4), intent(in) :: j1,j2
    end function eclass_2inte_eq
  end interface
  !
  interface
    function eclass_2inte1char_eq(i1,i2,j1,j2,k1,k2)
      !---------------------------------------------------------------------
      ! @ public
      ! Equality routine between two pairs of integers + 1 pair of chars
      !---------------------------------------------------------------------
      logical :: eclass_2inte1char_eq
      integer(kind=4),  intent(in) :: i1,i2
      integer(kind=4),  intent(in) :: j1,j2
      character(len=*), intent(in) :: k1,k2
    end function eclass_2inte1char_eq
  end interface
  !
  interface
    function eclass_2inte2char_eq(i1,i2,j1,j2,k1,k2,l1,l2)
      !---------------------------------------------------------------------
      ! @ public
      ! Equality routine between two pairs of integers + 2 pairs of chars
      !---------------------------------------------------------------------
      logical :: eclass_2inte2char_eq
      integer(kind=4),  intent(in) :: i1,i2
      integer(kind=4),  intent(in) :: j1,j2
      character(len=*), intent(in) :: k1,k2
      character(len=*), intent(in) :: l1,l2
    end function eclass_2inte2char_eq
  end interface
  !
  interface
    function eclass_dble_eq(a,b)
      !---------------------------------------------------------------------
      ! @ public
      ! Equality routine between two real*8
      ! WARNING: there is no tolerance here, because we assume we compare
      ! values which we know must be equal
      !---------------------------------------------------------------------
      logical :: eclass_dble_eq
      real(kind=8), intent(in) :: a
      real(kind=8), intent(in) :: b
    end function eclass_dble_eq
  end interface
  !
  interface
    function eclass_2dble_eq(x1,x2,y1,y2)
      !---------------------------------------------------------------------
      ! @ public
      ! Equality routine between two pairs of real*8 (e.g. coordinates)
      ! WARNING: there is no tolerance here, because we assume we compare
      ! values which we know must be equal
      !---------------------------------------------------------------------
      logical :: eclass_2dble_eq
      real(kind=8), intent(in) :: x1,x2
      real(kind=8), intent(in) :: y1,y2
    end function eclass_2dble_eq
  end interface
  !
  interface
    function eclass_2dble3inte_eq(x1,x2,y1,y2,i1,i2,j1,j2,k1,k2)
      !---------------------------------------------------------------------
      ! @ public
      ! Equality routine between two pairs of real*8 and two triplets of
      ! integer*4
      !---------------------------------------------------------------------
      logical :: eclass_2dble3inte_eq
      real(kind=8),    intent(in) :: x1,x2
      real(kind=8),    intent(in) :: y1,y2
      integer(kind=4), intent(in) :: i1,i2
      integer(kind=4), intent(in) :: j1,j2
      integer(kind=4), intent(in) :: k1,k2
    end function eclass_2dble3inte_eq
  end interface
  !
  interface
    function eclass_char_eq(a,b)
      !---------------------------------------------------------------------
      ! @ public
      ! Equality routine between two characters
      !---------------------------------------------------------------------
      logical :: eclass_char_eq
      character(len=*), intent(in) :: a
      character(len=*), intent(in) :: b
    end function eclass_char_eq
  end interface
  !
  interface
    subroutine eclass_inte(equiv,eclass)
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      logical,             external      :: equiv   ! l = equiv(i1,i2)
      type(eclass_inte_t), intent(inout) :: eclass  !
    end subroutine eclass_inte
  end interface
  !
  interface
    subroutine eclass_2inte(equiv,eclass)
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      logical,              external      :: equiv   !
      type(eclass_2inte_t), intent(inout) :: eclass  !
    end subroutine eclass_2inte
  end interface
  !
  interface
    subroutine eclass_2inte1char(equiv,eclass)
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      logical,                   external      :: equiv   !
      type(eclass_2inte1char_t), intent(inout) :: eclass  !
    end subroutine eclass_2inte1char
  end interface
  !
  interface
    subroutine eclass_2inte2char(equiv,eclass)
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      logical,                   external      :: equiv   !
      type(eclass_2inte2char_t), intent(inout) :: eclass  !
    end subroutine eclass_2inte2char
  end interface
  !
  interface
    subroutine eclass_dble(equiv,eclass)
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      logical,             external      :: equiv   !
      type(eclass_dble_t), intent(inout) :: eclass  !
    end subroutine eclass_dble
  end interface
  !
  interface
    subroutine eclass_2dble(equiv,eclass)
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      logical,              external      :: equiv   !
      type(eclass_2dble_t), intent(inout) :: eclass  !
    end subroutine eclass_2dble
  end interface
  !
  interface
    subroutine eclass_2dble1char(equiv,eclass)
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      logical,                   external      :: equiv   !
      type(eclass_2dble1char_t), intent(inout) :: eclass  !
    end subroutine eclass_2dble1char
  end interface
  !
  interface
    subroutine eclass_2dble3inte(equiv,eclass)
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      logical,                   external      :: equiv   !
      type(eclass_2dble3inte_t), intent(inout) :: eclass  !
    end subroutine eclass_2dble3inte
  end interface
  !
  interface
    subroutine eclass_char(equiv,eclass)
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      logical,             external      :: equiv   ! l = equiv(c1,c2)
      type(eclass_char_t), intent(inout) :: eclass  !
    end subroutine eclass_char
  end interface
  !
  interface
    subroutine reallocate_eclass_inte(eclass,nval,error)
      use gbl_message
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      type(eclass_inte_t), intent(inout) :: eclass
      integer(kind=4),     intent(in)    :: nval
      logical,             intent(inout) :: error
    end subroutine reallocate_eclass_inte
  end interface
  !
  interface
    subroutine reallocate_eclass_2inte(eclass,nval,error)
      use gbl_message
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      type(eclass_2inte_t), intent(inout) :: eclass
      integer(kind=4),      intent(in)    :: nval
      logical,              intent(inout) :: error
    end subroutine reallocate_eclass_2inte
  end interface
  !
  interface
    subroutine reallocate_eclass_2inte1char(eclass,nval,error)
      use gbl_message
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      type(eclass_2inte1char_t), intent(inout) :: eclass
      integer(kind=4),           intent(in)    :: nval
      logical,                   intent(inout) :: error
    end subroutine reallocate_eclass_2inte1char
  end interface
  !
  interface
    subroutine reallocate_eclass_2inte2char(eclass,nval,error)
      use gbl_message
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      type(eclass_2inte2char_t), intent(inout) :: eclass
      integer(kind=4),           intent(in)    :: nval
      logical,                   intent(inout) :: error
    end subroutine reallocate_eclass_2inte2char
  end interface
  !
  interface
    subroutine reallocate_eclass_dble(eclass,nval,error)
      use gbl_message
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      type(eclass_dble_t), intent(inout) :: eclass
      integer(kind=4),     intent(in)    :: nval
      logical,             intent(inout) :: error
    end subroutine reallocate_eclass_dble
  end interface
  !
  interface
    subroutine reallocate_eclass_2dble(eclass,nval,error)
      use gbl_message
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      type(eclass_2dble_t), intent(inout) :: eclass
      integer(kind=4),      intent(in)    :: nval
      logical,              intent(inout) :: error
    end subroutine reallocate_eclass_2dble
  end interface
  !
  interface
    subroutine reallocate_eclass_2dble1char(eclass,nval,error)
      use gbl_message
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      type(eclass_2dble1char_t), intent(inout) :: eclass
      integer(kind=4),           intent(in)    :: nval
      logical,                   intent(inout) :: error
    end subroutine reallocate_eclass_2dble1char
  end interface
  !
  interface
    subroutine reallocate_eclass_2dble3inte(eclass,nval,error)
      use gbl_message
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      type(eclass_2dble3inte_t), intent(inout) :: eclass
      integer(kind=4),           intent(in)    :: nval
      logical,                   intent(inout) :: error
    end subroutine reallocate_eclass_2dble3inte
  end interface
  !
  interface
    subroutine reallocate_eclass_char(eclass,nval,error)
      use gbl_message
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      type(eclass_char_t), intent(inout) :: eclass
      integer(kind=4),     intent(in)    :: nval
      logical,             intent(inout) :: error
    end subroutine reallocate_eclass_char
  end interface
  !
  interface
    subroutine free_eclass_inte(eclass,error)
      use gbl_message
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      type(eclass_inte_t), intent(inout) :: eclass
      logical,             intent(inout) :: error
    end subroutine free_eclass_inte
  end interface
  !
  interface
    subroutine free_eclass_2inte(eclass,error)
      use gbl_message
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      type(eclass_2inte_t), intent(inout) :: eclass
      logical,              intent(inout) :: error
    end subroutine free_eclass_2inte
  end interface
  !
  interface
    subroutine free_eclass_2inte1char(eclass,error)
      use gbl_message
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      type(eclass_2inte1char_t), intent(inout) :: eclass
      logical,                   intent(inout) :: error
    end subroutine free_eclass_2inte1char
  end interface
  !
  interface
    subroutine free_eclass_2inte2char(eclass,error)
      use gbl_message
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      type(eclass_2inte2char_t), intent(inout) :: eclass
      logical,                   intent(inout) :: error
    end subroutine free_eclass_2inte2char
  end interface
  !
  interface
    subroutine free_eclass_dble(eclass,error)
      use gbl_message
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      type(eclass_dble_t), intent(inout) :: eclass
      logical,             intent(inout) :: error
    end subroutine free_eclass_dble
  end interface
  !
  interface
    subroutine free_eclass_2dble(eclass,error)
      use gbl_message
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      type(eclass_2dble_t), intent(inout) :: eclass
      logical,              intent(inout) :: error
    end subroutine free_eclass_2dble
  end interface
  !
  interface
    subroutine free_eclass_2dble1char(eclass,error)
      use gbl_message
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      type(eclass_2dble1char_t), intent(inout) :: eclass
      logical,                   intent(inout) :: error
    end subroutine free_eclass_2dble1char
  end interface
  !
  interface
    subroutine free_eclass_2dble3inte(eclass,error)
      use gbl_message
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      type(eclass_2dble3inte_t), intent(inout) :: eclass
      logical,                   intent(inout) :: error
    end subroutine free_eclass_2dble3inte
  end interface
  !
  interface
    subroutine free_eclass_char(eclass,error)
      use gbl_message
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      type(eclass_char_t), intent(inout) :: eclass
      logical,             intent(inout) :: error
    end subroutine free_eclass_char
  end interface
  !
  interface
    subroutine eclass_getnext(eclass,iclass,ielem,found,error)
      use gbl_message
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !  Utility routine: get the index of the next element which is in the
      ! iclass-th class.
      !---------------------------------------------------------------------
      class(eclass_common_t), intent(in)    :: eclass  ! The equivalence classes
      integer(kind=4),        intent(in)    :: iclass  ! The ith equivalence class we search into
      integer(kind=4),        intent(inout) :: ielem   ! Starting point (can be 0) and next (output) value found
      logical,                intent(out)   :: found   ! Found a new element?
      logical,                intent(inout) :: error   ! Logical error flag
    end subroutine eclass_getnext
  end interface
  !
  interface
    subroutine eclass_getprev(eclass,iclass,ielem,found,error)
      use gbl_message
      use eclass_types
      !---------------------------------------------------------------------
      ! @ public
      !  Utility routine: get the index of the previous element which is in
      ! the iclass-th class.
      !---------------------------------------------------------------------
      class(eclass_common_t), intent(in)    :: eclass  ! The equivalence classes
      integer(kind=4),        intent(in)    :: iclass  ! The ith equivalence class we search into
      integer(kind=4),        intent(inout) :: ielem   ! Starting point (can be N+1) and previous (output) value found
      logical,                intent(out)   :: found   ! Found a new element?
      logical,                intent(inout) :: error   ! Logical error flag
    end subroutine eclass_getprev
  end interface
  !
  interface
    function gag_erfinv(x0)
      use phys_const
      !-----------------------------------------------------------------------
      ! @ public
      ! This subroutine calculates the inverse error function.
      !-----------------------------------------------------------------------
      real(kind=8) :: gag_erfinv
      real(kind=8), intent(in) :: x0
    end function gag_erfinv
  end interface
  !
  interface
    function gag_erfcinv(x)
      !-----------------------------------------------------------------------
      ! @ public
      ! This subroutine calculates the inverse complementary error function.
      !-----------------------------------------------------------------------
      real(kind=8) :: gag_erfcinv
      real(kind=8), intent(in) :: x
    end function gag_erfcinv
  end interface
  !
  interface
    subroutine gr4_extrema (nxy,z,bval,eval,zmin,zmax,nmin,nmax)
      use gildas_def
      use gbl_message
      !$ use omp_lib
      !---------------------------------------------------------------------
      ! @ public-mandatory (because symbol is renamed elsewhere)
      ! Find extrema of a (Real*4) array.
      ! +/- Infinity are considered as valid extrema is this routine
      ! See GR4_MINMAX for a version which ignores Infinity
      !
      !     Ignore NaNs and all "blanked" values.
      !---------------------------------------------------------------------
      integer(kind=size_length), intent(in)    :: nxy     ! Number of values
      real(kind=4),              intent(in)    :: z(nxy)  ! Values
      real(kind=4),              intent(in)    :: bval    ! Blanking
      real(kind=4),              intent(in)    :: eval    ! Tolerance
      real(kind=4),              intent(inout) :: zmin    ! Unchanged if no valid value
      real(kind=4),              intent(inout) :: zmax    ! Unchanged if no valid value
      integer(kind=size_length), intent(out)   :: nmin    ! Set to 0 if no valid value
      integer(kind=size_length), intent(out)   :: nmax    ! Set to 0 if no valid value
    end subroutine gr4_extrema
  end interface
  !
  interface
    subroutine gr8_extrema (nxy,z,bval,eval,zmin,zmax,nmin,nmax)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-mandatory (because symbol is renamed elsewhere)
      ! Find extrema of a (Real*8) array
      ! +/- Infinity are considered as valid extrema is this routine
      ! See GR8_MINMAX for a version which ignores Infinity
      !!
      !     Ignore NaNs and all "blanked" values.
      !---------------------------------------------------------------------
      integer(kind=size_length), intent(in)    :: nxy     ! Number of values
      real(kind=8),              intent(in)    :: z(nxy)  ! Values
      real(kind=4),              intent(in)    :: bval    ! Blanking
      real(kind=4),              intent(in)    :: eval    ! Tolerance
      real(kind=4),              intent(inout) :: zmin    ! Unchanged if no valid value
      real(kind=4),              intent(inout) :: zmax    ! Unchanged if no valid value
      integer(kind=size_length), intent(out)   :: nmin    ! Set to 0 if no valid value
      integer(kind=size_length), intent(out)   :: nmax    ! Set to 0 if no valid value
    end subroutine gr8_extrema
  end interface
  !
  interface
    subroutine gr4_minmax(nxy,z,bval,eval,zmin,zmax,nmin,nmax)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-mandatory (because symbol is used elsewhere)
      ! Protect against NaN and INFs even without blanking
      !---------------------------------------------------------------------
      integer(kind=size_length), intent(in)  :: nxy     !
      real(kind=4),              intent(in)  :: z(nxy)  !
      real(kind=4),              intent(in)  :: bval    !
      real(kind=4),              intent(in)  :: eval    !
      real(kind=4),              intent(out) :: zmin    !
      real(kind=4),              intent(out) :: zmax    !
      integer(kind=size_length), intent(out) :: nmin    !
      integer(kind=size_length), intent(out) :: nmax    !
    end subroutine gr4_minmax
  end interface
  !
  interface
    subroutine gr8_minmax(nxy,z,bval,eval,zmin,zmax,nmin,nmax)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-mandatory (because symbol is used elsewhere)
      ! Protect against NaN and INFs even without blanking
      !---------------------------------------------------------------------
      integer(kind=size_length), intent(in)  :: nxy     !
      real(kind=8),              intent(in)  :: z(nxy)  !
      real(kind=8),              intent(in)  :: bval    !
      real(kind=8),              intent(in)  :: eval    !
      real(kind=8),              intent(out) :: zmin    !
      real(kind=8),              intent(out) :: zmax    !
      integer(kind=size_length), intent(out) :: nmin    !
      integer(kind=size_length), intent(out) :: nmax    !
    end subroutine gr8_minmax
  end interface
  !
  interface
    subroutine gr4_median(data,ndata,bval,eval,median,error)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      integer(kind=size_length), intent(in)    :: ndata        ! Array size
      real(kind=4),              intent(in)    :: data(ndata)  ! Data
      real(kind=4),              intent(in)    :: bval         ! Blanking value
      real(kind=4),              intent(in)    :: eval         ! Tolerance
      real(kind=4),              intent(inout) :: median       ! Median of input array
      logical,                   intent(inout) :: error        ! Logical error flag
    end subroutine gr4_median
  end interface
  !
  interface
    subroutine gr8_median(data,ndata,bval,eval,median,error)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-mandatory (because symbol is used elsewhere)
      !---------------------------------------------------------------------
      integer(kind=size_length), intent(in)    :: ndata        ! Array size
      real(kind=8),              intent(in)    :: data(ndata)  ! Data
      real(kind=8),              intent(in)    :: bval         ! Blanking value
      real(kind=8),              intent(in)    :: eval         ! Tolerance
      real(kind=8),              intent(inout) :: median       ! Median of input array
      logical,                   intent(inout) :: error        ! Logical error flag
    end subroutine gr8_median
  end interface
  !
  interface
    subroutine gr4_dicho(np,x,xval,ival)
      use gildas_def
      !---------------------------------------------------------------------
      ! @ public-mandatory (because symbol is used elsewhere)
      !  Find ival such as
      !    X(ival-1) < xval <= X(ival)     (ceiling mode)
      !  or
      !    X(ival) <= xval < X(ival+1)     (floor mode)
      ! for input data ordered. Use a dichotomic search for that.
      !---------------------------------------------------------------------
      integer(kind=size_length), intent(in)  :: np     ! Number of input points
      real(kind=4),              intent(in)  :: x(np)  ! Input ordered Values
      real(kind=4),              intent(in)  :: xval   ! The value we search for
      integer(kind=size_length), intent(out) :: ival   ! Position in the array
    end subroutine gr4_dicho
  end interface
  !
  interface
    subroutine gr8_dicho(np,x,xval,ceil,ival,error)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      !  Find ival such as
      !    X(ival-1) < xval <= X(ival)     (ceiling mode)
      !  or
      !    X(ival) <= xval < X(ival+1)     (floor mode)
      ! for input data ordered. Use a dichotomic search for that.
      !---------------------------------------------------------------------
      integer(kind=size_length), intent(in)    :: np     ! Number of input points
      real(kind=8),              intent(in)    :: x(np)  ! Input ordered Values
      real(kind=8),              intent(in)    :: xval   ! The value we search for
      logical,                   intent(in)    :: ceil   ! Ceiling or floor mode?
      integer(kind=size_length), intent(out)   :: ival   ! Position in the array
      logical,                   intent(inout) :: error  ! Logical error flag
    end subroutine gr8_dicho
  end interface
  !
  interface
    subroutine gi4_dicho(np,x,xval,ceil,ival,error)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      !  Find ival such as
      !    X(ival-1) < xval <= X(ival)     (ceiling mode)
      !  or
      !    X(ival) <= xval < X(ival+1)     (floor mode)
      ! for input data ordered. Use a dichotomic search for that.
      !---------------------------------------------------------------------
      integer(kind=size_length), intent(in)    :: np     ! Number of input points
      integer(kind=4),           intent(in)    :: x(np)  ! Input ordered Values
      integer(kind=4),           intent(in)    :: xval   ! The value we search for
      logical,                   intent(in)    :: ceil   ! Ceiling or floor mode?
      integer(kind=size_length), intent(out)   :: ival   ! Position in the array
      logical,                   intent(inout) :: error  ! Logical error flag
    end subroutine gi4_dicho
  end interface
  !
  interface
    subroutine gi8_dicho(np,x,xval,ceil,ival,error)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      !  Find ival such as
      !    X(ival-1) < xval <= X(ival)     (ceiling mode)
      !  or
      !    X(ival) <= xval < X(ival+1)     (floor mode)
      ! for input data ordered. Use a dichotomic search for that.
      !---------------------------------------------------------------------
      integer(kind=size_length), intent(in)    :: np     ! Number of input points
      integer(kind=8),           intent(in)    :: x(np)  ! Input ordered Values
      integer(kind=8),           intent(in)    :: xval   ! The value we search for
      logical,                   intent(in)    :: ceil   ! Ceiling or floor mode?
      integer(kind=size_length), intent(out)   :: ival   ! Position in the array
      logical,                   intent(inout) :: error  ! Logical error flag
    end subroutine gi8_dicho
  end interface
  !
  interface
    subroutine gr4_mean(x,nelem,bval,eval,out)
      !$ use omp_lib
      use gildas_def
      !---------------------------------------------------------------------
      ! @ public
      !   Protected against NaNs and Using Blanking Values. If Blanking
      ! enabled, will return blanking value if no valid result. If Blanking
      ! is not enabled, will return NaN if no valid result.
      !   R*4 version.
      !---------------------------------------------------------------------
      integer(kind=size_length), intent(in)  :: nelem     ! Number of data values
      real(kind=4),              intent(in)  :: x(nelem)  ! Data values to compute
      real(kind=4),              intent(in)  :: bval      ! Blanking value
      real(kind=4),              intent(in)  :: eval      ! Blanking tolerance
      real(kind=4),              intent(out) :: out       ! Output scalar value
    end subroutine gr4_mean
  end interface
  !
  interface
    subroutine gr8_mean(x,nelem,bval,eval,out)
      !$ use omp_lib
      use gildas_def
      !---------------------------------------------------------------------
      ! @ public
      !   Protected against NaNs and Using Blanking Values. If Blanking
      ! enabled, will return blanking value if no valid result. If Blanking
      ! is not enabled, will return NaN if no valid result.
      !   R*8 version.
      !---------------------------------------------------------------------
      integer(kind=size_length), intent(in)  :: nelem     ! Number of data values
      real(kind=8),              intent(in)  :: x(nelem)  ! Data values to compute
      real(kind=8),              intent(in)  :: bval      ! Blanking value
      real(kind=8),              intent(in)  :: eval      ! Blanking tolerance
      real(kind=8),              intent(out) :: out       ! Output scalar value
    end subroutine gr8_mean
  end interface
  !
  interface gi0_dicho_with_user_ltgt
    subroutine gi4_dicho_with_user_ltgt(np,ceil,ival,ult,ugt,error)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic gi0_dicho_with_user_ltgt
      !  Find ival such as
      !    X(ival-1) < xval <= X(ival)     (ceiling mode)
      !  or
      !    X(ival) <= xval < X(ival+1)     (floor mode)
      ! for input data ordered. Use a dichotomic search for that.
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)    :: np     ! Number of elements in array
      logical,         intent(in)    :: ceil   ! Ceiling mode?
      integer(kind=4), intent(out)   :: ival   ! Deduced position in the array
      logical,         external      :: ult    ! User lower than
      logical,         external      :: ugt    ! User greater than
      logical,         intent(inout) :: error  ! Logical error flag
    end subroutine gi4_dicho_with_user_ltgt
    subroutine gi8_dicho_with_user_ltgt(np,ceil,ival,ult,ugt,error)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic gi0_dicho_with_user_ltgt
      !  Find ival such as
      !    X(ival-1) < xval <= X(ival)     (ceiling mode)
      !  or
      !    X(ival) <= xval < X(ival+1)     (floor mode)
      ! for input data ordered. Use a dichotomic search for that.
      !---------------------------------------------------------------------
      integer(kind=8), intent(in)    :: np     ! Number of elements in array
      logical,         intent(in)    :: ceil   ! Ceiling mode?
      integer(kind=8), intent(out)   :: ival   ! Deduced position in the array
      logical,         external      :: ult    ! User lower than
      logical,         external      :: ugt    ! User greater than
      logical,         intent(inout) :: error  ! Logical error flag
    end subroutine gi8_dicho_with_user_ltgt
  end interface gi0_dicho_with_user_ltgt
  !
  interface
    subroutine extoin(fit,pint)
      use fit_minuit
      !----------------------------------------------------------------------
      ! @ public
      !      Transforms the external parameter values X  to internal
      !      values in the dense array PINT.   Function PINTF is used.
      !----------------------------------------------------------------------
      type(fit_minuit_t), intent(inout) :: fit      !
      real(kind=8),       intent(out)   :: pint(2)  ! Dense array
    end subroutine extoin
  end interface
  !
  interface
    subroutine hesse(fit,fcn)
      use gbl_message
      use fit_minuit
      !----------------------------------------------------------------------
      ! @ public
      !      Calculates the full second-derivative matrix of FCN
      !      by taking finite differences.   Includes some safeguards
      !      against non-positive-definite matrices, and it may set
      !       off-diagonal elements to zero in attempt to force
      !      positiveness.
      !----------------------------------------------------------------------
      type(fit_minuit_t), intent(inout) :: fit  !
      external                          :: fcn  ! Function to minimise
    end subroutine hesse
  end interface
  !
  interface
    subroutine intoex(fit,pint)
      use fit_minuit
      !----------------------------------------------------------------------
      ! @ public
      !      Transforms from internal coordinates (PINT) to external
      !      parameters (U).   The minimizing routines which work in
      !      internal coordinates call this routine before calling FCN.
      !----------------------------------------------------------------------
      type(fit_minuit_t), intent(inout) :: fit      !
      real(kind=8),       intent(in)    :: pint(2)  ! Dense array
    end subroutine intoex
  end interface
  !
  interface
    subroutine migrad(fit,fcn,ier)
      use gbl_message
      use fit_minuit
      !----------------------------------------------------------------------
      ! @ public
      !      Performs a local function minimization using basically the
      !      method of DAVIDON-FLETCHER-POWELL as modified by FLETCHER
      !      Ref. -- FLETCHER, COMP.J. 13,317 (1970)   "Switching method"
      !----------------------------------------------------------------------
      type(fit_minuit_t), intent(inout) :: fit  !
      external                          :: fcn  ! Function to minimise
      integer(kind=4),    intent(out)   :: ier  ! Error condition flag for HESSE
    end subroutine migrad
  end interface
  !
  interface
    function pintf(fit,pexti,i)
      use gbl_message
      use fit_minuit
      !----------------------------------------------------------------------
      ! @ public
      !      Calculates the internal parameter value PINTF corresponding
      !      to the external value PEXTI for parameter I.
      !----------------------------------------------------------------------
      real(kind=8) :: pintf  ! Function value on return
      type(fit_minuit_t), intent(inout) :: fit    !
      real(kind=8),       intent(inout) :: pexti  ! External value
      integer(kind=4),    intent(in)    :: i      ! Parameter number
    end function pintf
  end interface
  !
  interface
    subroutine simplx(fit,fcn,ier)
      use gbl_message
      use fit_minuit
      !----------------------------------------------------------------------
      ! @ public
      !      Performs a minimization using the SIMPLEX method of NELDER
      !      and MEAD (REF. -- COMP. J. 7,308 (1965)).
      !----------------------------------------------------------------------
      type(fit_minuit_t), intent(inout) :: fit  !
      external                          :: fcn  ! Function to minimize
      integer(kind=4),    intent(out)   :: ier  ! Error condition flag
    end subroutine simplx
  end interface
  !
  interface
    subroutine fourt_set_usage(status)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      !   Toggle the use of FFTW and its Debug mode, and
      !   return the previous status
      !---------------------------------------------------------------------
      logical, intent(inout) :: status(2)  !  Use and Debug FFTW code ?
    end subroutine fourt_set_usage
  end interface
  !
  interface
    subroutine fourt_get_usage(status) 
      !---------------------------------------------------------------------
      ! @ public
      !   Toggle the use of FFTW and its Debug mode, and
      !   return the previous status 
      !---------------------------------------------------------------------
      logical, intent(out) :: status(2)    !  Use and Debug FFTW code ?
    end subroutine fourt_get_usage
  end interface
  !
  interface
    subroutine fourt_plan(data,nn,ndim,isign,iform)
      !$ use omp_lib
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-mandatory (because symbol is renamed elsewhere)
      ! Fast Fourier Transform Planner
      !
      ! If the data is of type Real (IFORM=0), the imaginary part should be
      ! set to 0. WORK should be dimensionned to twice the largest dimension.
      !
      ! NOTES:
      !     Calls FFTW when available, if FFTW_USE is set.
      !     Calls specialized procedures for 1-D and 2-D FFT with powers of 2,
      !         based on near-optimal Split-Radix method of P.Duhamel.
      !     Calls the Cooley-Tukey FOURTCT in other cases.
      !---------------------------------------------------------------------
      complex(kind=4) :: data(*)  ! Complex array of data             Input/Output
      integer(kind=4) :: nn(*)    ! Dimensions of data array          Input
      integer(kind=4) :: ndim     ! Number of dimensions              Input
      integer(kind=4) :: isign    ! Sign of FT (-1 Direct, 1 Inverse) Input
      integer(kind=4) :: iform    ! Type of data (0 Real, 1 Complex)  (Unused)
    end subroutine fourt_plan
  end interface
  !
  interface
    subroutine fourt(data,nn,ndim,isign,iform,work)
      !$ use omp_lib
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-mandatory (because symbol is renamed elsewhere)
      ! Fast Fourier Transform
      !
      ! If the data is of type Real (IFORM=0), the imaginary part should be
      ! set to 0. WORK should be dimensioned to twice the largest dimension.
      !
      ! NOTES:
      !  For COMPLEX (IFORM=1) transforms
      !     Calls FFTW when available
      !     Calls specialized procedures for 1-D and 2-D FFT with powers of 2,
      !         based on near-optimal Split-Radix method of P.Duhamel.
      !     Calls the Cooley-Tukey FOURTCT in other cases.
      !  For REAL (IFORM=0) transforms
      !     Calls FFTW when available, but in COMPLEX mode only
      !     Calls specialized procedures for 1-D and 2-D FFT with powers of 2.
      !     Calls the Cooley-Tukey FOURTCT in other cases.
      !  data(*) is declared as "complex (*)" here for the interface,
      !     but passed to subroutines treating it as "real (2,*)"
      !---------------------------------------------------------------------
      complex(kind=4), intent(inout) :: data(*)  ! Complex array of data
      integer(kind=4), intent(in)    :: nn(*)    ! Dimensions of data array
      integer(kind=4), intent(in)    :: ndim     ! Number of dimensions
      integer(kind=4), intent(in)    :: isign    ! Sign of FT (-1 Direct, 1 Inverse)
      integer(kind=4), intent(in)    :: iform    ! Type of data (0 Real, 1 Complex)
      real(kind=4)                   :: work(*)  ! Work space
    end subroutine fourt
  end interface
  !
  interface
    function power_of_two(dim)
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      integer(kind=4) :: power_of_two     ! Value on return
      integer(kind=4), intent(in) :: dim  !
    end function power_of_two
  end interface
  !
  interface
    subroutine gi4_round_forfft(isize,osize,error,tolerance,exponent)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      !
      !  Find the nearest number in the form 2^n 3^p 5^q with p and q
      ! smaller than Exponent (can be 0, then only powers of two are
      ! returned.)
      !
      !  Round to near if within Tolerance. Use Ceiling if not.
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)           :: isize      ! Input size
      integer(kind=4), intent(out)          :: osize      ! Output size
      real(kind=4),    intent(in), optional :: tolerance  ! Tolerance
      integer(kind=4), intent(in), optional :: exponent   ! Max exponent
      logical,         intent(inout)        :: error      !
    end subroutine gi4_round_forfft
  end interface
  !
  interface
    function s_gaussian1d(x,xcent,fwhm)
      !---------------------------------------------------------------------
      ! @ public
      ! Compute gaussian value at X, peaks at 1 (single precision)
      !---------------------------------------------------------------------
      real(kind=4) :: s_gaussian1d
      real(kind=4), intent(in) :: x
      real(kind=4), intent(in) :: xcent
      real(kind=4), intent(in) :: fwhm
    end function s_gaussian1d
  end interface
  !
  interface
    function d_gaussian1d(x,xcent,fwhm)
      use phys_const
      !---------------------------------------------------------------------
      ! @ public
      ! Compute gaussian value at X, peaks at 1 (double precision)
      !---------------------------------------------------------------------
      real(kind=8) :: d_gaussian1d
      real(kind=8), intent(in) :: x
      real(kind=8), intent(in) :: xcent
      real(kind=8), intent(in) :: fwhm
    end function d_gaussian1d
  end interface
  !
  interface
    function s_normal1d(x,xcent,sigma)
      use phys_const
      !---------------------------------------------------------------------
      ! @ public
      ! Compute normal distribution value at X, area is 1 (single precision)
      !---------------------------------------------------------------------
      real(kind=4) :: s_normal1d
      real(kind=4), intent(in) :: x
      real(kind=4), intent(in) :: xcent
      real(kind=4), intent(in) :: sigma
    end function s_normal1d
  end interface
  !
  interface
    function d_normal1d(x,xcent,sigma)
      use phys_const
      !---------------------------------------------------------------------
      ! @ public
      ! Compute normal distribution value at X, area is 1 (double precision)
      !---------------------------------------------------------------------
      real(kind=8) :: d_normal1d
      real(kind=8), intent(in) :: x
      real(kind=8), intent(in) :: xcent
      real(kind=8), intent(in) :: sigma
    end function d_normal1d
  end interface
  !
  interface
    subroutine gauss2d_convolution(a1,b1,t1,a2,b2,t2,a3,b3,t3,error)
      !---------------------------------------------------------------------
      ! @ public
      ! Compute the parameters of the 2D gaussian resulting from the
      ! convolution of 2 2D gaussians:
      !   1 * 2 => 3
      ! Knowing 1 and 2 find 3.
      !---------------------------------------------------------------------
      real(kind=4), intent(in)    :: a1    ! [same] First gaussian major axis
      real(kind=4), intent(in)    :: b1    ! [same] First gaussian minor axis
      real(kind=4), intent(in)    :: t1    ! [rad]  First gaussian position angle
      real(kind=4), intent(in)    :: a2    ! [same] Second gaussian major axis
      real(kind=4), intent(in)    :: b2    ! [same] Second gaussian minor axis
      real(kind=4), intent(in)    :: t2    ! [rad]  Second gaussian position angle
      real(kind=4), intent(out)   :: a3    ! [same] Result major axis
      real(kind=4), intent(out)   :: b3    ! [same] Result minor axis
      real(kind=4), intent(out)   :: t3    ! [rad]  Result position angle
      logical,      intent(inout) :: error ! Logical error flag
    end subroutine gauss2d_convolution
  end interface
  !
  interface
    subroutine gauss2d_deconvolution(a1,b1,t1,a3,b3,t3,a2,b2,t2,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! Compute the parameters of the 2D gaussian resulting from the
      ! deconvolution of 2 2D gaussians:
      !   1 * 2 => 3
      ! Knowing 1 and 3 find 2.
      !---------------------------------------------------------------------
      real(kind=4), intent(in)    :: a1    ! [same] First gaussian major axis
      real(kind=4), intent(in)    :: b1    ! [same] First gaussian minor axis
      real(kind=4), intent(in)    :: t1    ! [rad]  First gaussian position angle
      real(kind=4), intent(in)    :: a3    ! [same] Result major axis
      real(kind=4), intent(in)    :: b3    ! [same] Result minor axis
      real(kind=4), intent(in)    :: t3    ! [rad]  Result position angle
      real(kind=4), intent(out)   :: a2    ! [same] Second gaussian major axis
      real(kind=4), intent(out)   :: b2    ! [same] Second gaussian minor axis
      real(kind=4), intent(out)   :: t2    ! [rad]  Second gaussian position angle
      logical,      intent(inout) :: error ! Logical error flag
    end subroutine gauss2d_deconvolution
  end interface
  !
  interface
    subroutine gmath_message_set_id(id)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! Alter library id into input id. Should be called by the library
      ! which wants to share its id with the current one.
      !---------------------------------------------------------------------
      integer, intent(in) :: id
    end subroutine gmath_message_set_id
  end interface
  !
  interface
    subroutine eulmat (psi,the,phi,mat)
      !---------------------------------------------------------------------
      ! @ public
      !  from Didier Despois 1980
      !  modified 30 november 1984 by Michel Perault
      !  matrice de changement de coordonnees pour une rotation d'angles d'Euler
      !  PSI, THE et PHI, given in radians.
      !  Multiplication of the euclidian coordinates of a vector in the original base
      !  by this matrix gives the coordinates in the rotated base.
      !  For example, the transformation from galactic II coordinates to equatorial
      !  1950 coordinates is obtained with PSI=33., THETA=-62.6, PHI=-282.25 degrees.
      !  The reverse transformation with PSI=282.25, THETA=62.5, PHI=-33 degrees.
      !---------------------------------------------------------------------
      real(kind=8), intent(in)  :: psi       ! Euler angles (radians)
      real(kind=8), intent(in)  :: the       ! Euler angles (radians)
      real(kind=8), intent(in)  :: phi       ! Euler angles (radians)
      real(kind=8), intent(out) :: mat(3,3)  ! transformation matrix
    end subroutine eulmat
  end interface
  !
  interface
    subroutine mulmat (mat1,mat2,mat)
      !---------------------------------------------------------------------
      ! @ public
      !  multiplication of two 3 by 3 matrices
      !  Michel Perault - 1 december 1984.
      !  this routine computes MAT = MAT2 x MAT1
      !  it could be a little faster, but also less compact
      !  take care that MAT ought to be different from MAT1 and MAT2
      !---------------------------------------------------------------------
      real(kind=8), intent(in)  :: mat1(3,3)  !
      real(kind=8), intent(in)  :: mat2(3,3)  !
      real(kind=8), intent(out) :: mat(3,3)   !
    end subroutine mulmat
  end interface
  !
  interface
    subroutine matvec (mat1,mat2,mat)
      !---------------------------------------------------------------------
      ! @ public
      !  multiplication of 1 3-D vector by a 3x3 matrix
      !  Michel Perault - 1 december 1984.
      !  this routine computes MAT = MAT2 x MAT1
      !  take care that MAT must be different from MAT1 and MAT2
      !---------------------------------------------------------------------
      real(kind=8), intent(in)  :: mat1(3)    !
      real(kind=8), intent(in)  :: mat2(3,3)  !
      real(kind=8), intent(out) :: mat(3)     !
    end subroutine matvec
  end interface
  !
  interface
    subroutine transp (mat1,mat2)
      !---------------------------------------------------------------------
      ! @ public
      !  Transposee d'une matrice 3x3
      !  20 Septembre 1985 - Michel Perault - POM Version 2.0
      !  Appel : call TRANSP (MAT1,MAT2)  result in MAT2 = transp (MAT1)
      !---------------------------------------------------------------------
      real(kind=8), intent(in)  :: mat1(9)  !
      real(kind=8), intent(out) :: mat2(9)  !
    end subroutine transp
  end interface
  !
  interface
    subroutine matinv3(a,b)
      !---------------------------------------------------------------------
      ! @ public
      ! Performs a direct calculation of the inverse of a 3x3 matrix.
      !---------------------------------------------------------------------
      real(kind=8), intent(in)  :: A(3,3)  ! Matrix
      real(kind=8), intent(out) :: B(3,3)  ! Inverse matrix
    end subroutine matinv3
  end interface
  !
  interface
    subroutine gr8_sort(x,xwork,key,n)
      !---------------------------------------------------------------------
      ! @ public-mandatory (because symbol is used elsewhere)
      !  Reorder a real*8 array by increasing order using the sorted indexes
      ! computed by a G*_TRIE subroutine
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)    :: n         ! Length of arrays
      real(kind=8),    intent(inout) :: x(n)      ! Unsorted array
      real(kind=8)                   :: xwork(n)  ! Working buffer
      integer(kind=4), intent(in)    :: key(n)    ! Integer array of sorted indexes
    end subroutine gr8_sort
  end interface
  !
  interface
    subroutine gr4_sort(x,xwork,key,n)
      !---------------------------------------------------------------------
      ! @ public-mandatory (because symbol is used elsewhere)
      !  Reorder a real*4 array by increasing order using the sorted indexes
      ! computed by a G*_TRIE subroutine
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)    :: n         !
      real(kind=4),    intent(inout) :: x(n)      !
      real(kind=4)                   :: xwork(n)  ! Working buffer
      integer(kind=4), intent(in)    :: key(n)    !
    end subroutine gr4_sort
  end interface
  !
  interface
    subroutine gi4_sort(x,xwork,key,n)
      !---------------------------------------------------------------------
      ! @ public-mandatory (because symbol is used elsewhere)
      !  Reorder an integer*4 array by increasing order using the sorted
      ! indexes computed by a G*_TRIE subroutine
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)    :: n         ! Length of arrays
      integer(kind=4), intent(inout) :: x(n)      ! Unsorted array
      integer(kind=4)                :: xwork(n)  ! Working buffer
      integer(kind=4), intent(in)    :: key(n)    ! Integer array of sorted indexes
    end subroutine gi4_sort
  end interface
  !
  interface
    subroutine gi8_sort(x,xwork,key,n)
      !---------------------------------------------------------------------
      ! @ public-mandatory (because symbol is used elsewhere)
      !  Reorder an integer*8 array by increasing order using the sorted
      ! indexes computed by a G*_TRIE subroutine
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)    :: n         ! Length of arrays
      integer(kind=8), intent(inout) :: x(n)      ! Unsorted array
      integer(kind=8)                :: xwork(n)  ! Working buffer
      integer(kind=4), intent(in)    :: key(n)    ! Integer array of sorted indexes
    end subroutine gi8_sort
  end interface
  !
  interface
    subroutine gch_sort(x,xwork,key,nc,n)
      !---------------------------------------------------------------------
      ! @ public-mandatory (because symbol is used elsewhere)
      !   Reorder a character array by increasing order using the sorted
      ! indexes computed by a G*_TRIE subroutine
      !---------------------------------------------------------------------
      integer(kind=4),   intent(in)    :: nc        ! Size of strings
      character(len=nc), intent(inout) :: x(*)      ! The array
      character(len=nc)                :: xwork(*)  ! Work buffer
      integer(kind=4),   intent(in)    :: key(*)    ! Integer array of sorted indexes
      integer(kind=4),   intent(in)    :: n         ! Length of arrays
    end subroutine gch_sort
  end interface
  !
  interface
    subroutine gl_sort(x,xwork,key,n)
      !---------------------------------------------------------------------
      ! @ public-mandatory (because symbol is used elsewhere)
      !  Reorder a logical*4 array by increasing order using the sorted
      ! indexes computed by a G*_TRIE subroutine
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)    :: n         ! Length of arrays
      logical,         intent(inout) :: x(n)      ! Unsorted array
      logical                        :: xwork(n)  ! Working buffer
      integer(kind=4), intent(in)    :: key(n)    ! Integer array of sorted indexes
    end subroutine gl_sort
  end interface
  !
  interface
    function gr8_in (x0,y0,ngon,gons,bound)
      !---------------------------------------------------------------------
      ! @ public
      ! Find if a point is within a n-gon.
      !
      ! This uses the Ray casting algorithm, counting how many times a ray
      ! starting from the point crosses the polygon boundaries. Note that
      ! there are critical conditions to be taken into account when the
      ! point is on a vertex or on a boundary or when the ray strikes
      ! through a vertex.
      ! References:
      !  https://en.wikipedia.org/wiki/Point_in_polygon
      !  https://rosettacode.org/wiki/Ray-casting_algorithm
      !---------------------------------------------------------------------
      logical :: gr8_in  ! Function value on return
      real(kind=8),    intent(in) :: x0,y0      ! Coordinate of point to test
      integer(kind=4), intent(in) :: ngon       ! Current number of summits
      real(kind=8),    intent(in) :: gons(:,:)  ! Description of polygon
      real(kind=8),    intent(in) :: bound(5)   ! Polygon boundary
    end function gr8_in
  end interface
  !
  interface gch_trie
    subroutine gch_trie_i4(x,it,n,nc,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic gch_trie
      !  Sorting program that uses a quicksort algorithm.
      !  Applies for an input array of CHARACTER(len=*) values. Also returns
      ! an array of indexes sorted for increasing order of X which can used
      ! in GCH_SORT to reorder other arrays
      ! ---
      !  This version for I*4 indices
      !---------------------------------------------------------------------
      integer(kind=4),   intent(in)    :: n      ! Length of arrays
      integer(kind=4),   intent(in)    :: nc     ! Size of strings
      character(len=nc), intent(inout) :: x(n)   ! Unsorted array
      integer(kind=4),   intent(out)   :: it(n)  ! Integer array of sorted indexes
      logical,           intent(out)   :: error  ! Error flag
    end subroutine gch_trie_i4
    subroutine gch_trie_i8(x,it,n,nc,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic gch_trie
      !  Sorting program that uses a quicksort algorithm.
      !  Applies for an input array of CHARACTER(len=*) values. Also returns
      ! an array of indexes sorted for increasing order of X which can used
      ! in GCH_SORT to reorder other arrays
      ! ---
      !  This version for I*8 indices
      !---------------------------------------------------------------------
      integer(kind=8),   intent(in)    :: n      ! Length of arrays
      integer(kind=4),   intent(in)    :: nc     ! Size of strings
      character(len=nc), intent(inout) :: x(n)   ! Unsorted array
      integer(kind=8),   intent(out)   :: it(n)  ! Integer array of sorted indexes
      logical,           intent(out)   :: error  ! Error flag
    end subroutine gch_trie_i8
  end interface gch_trie
  !
  interface gi0_quicksort_index_with_user_gtge
    subroutine gi4_quicksort_index_with_user_gtge(x,n,ugt,uge,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic gi0_quicksort_index_with_user_gtge
      ! Sort an integer*4 index array according to an external comparison
      ! criteria. The index array can then be used by gi4_quicksort_array
      ! to sort an associated array.
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)    :: n      ! Length of index array
      integer(kind=4), intent(inout) :: x(n)   ! Index array to be sorted
      logical,         external      :: ugt    ! User greater than
      logical,         external      :: uge    ! User greater than or equal
      logical,         intent(out)   :: error  ! Error status
    end subroutine gi4_quicksort_index_with_user_gtge
    subroutine gi8_quicksort_index_with_user_gtge(x,n,ugt,uge,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic gi0_quicksort_index_with_user_gtge
      ! Sort an integer*8 index array according to an external comparison
      ! criteria. The index array can then be used by gi4_quicksort_array
      ! to sort an associated array.
      !---------------------------------------------------------------------
      integer(kind=8), intent(in)    :: n      ! Length of index array
      integer(kind=8), intent(inout) :: x(n)   ! Index array to be sorted
      logical,         external      :: ugt    ! User greater than
      logical,         external      :: uge    ! User greater than or equal
      logical,         intent(out)   :: error  ! Error status
    end subroutine gi8_quicksort_index_with_user_gtge
  end interface gi0_quicksort_index_with_user_gtge
  !
  interface gi4_trie
    subroutine gi4_trie_i4(x,it,n,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic gi4_trie
      !  Sorting program that uses a quicksort algorithm.
      !  Applies for an input array of integer*4 values. Also returns an
      ! array of indexes sorted for increasing order of X which can used in
      ! GI4_SORT to reorder other arrays
      ! ---
      !  This version for I*4 indices
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)    :: n      ! Length of arrays
      integer(kind=4), intent(inout) :: x(n)   ! Unsorted array
      integer(kind=4), intent(out)   :: it(n)  ! Integer array of sorted indexes
      logical,         intent(out)   :: error  ! Error flag
    end subroutine gi4_trie_i4
    subroutine gi4_trie_i8(x,it,n,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic gi4_trie
      !  Sorting program that uses a quicksort algorithm.
      !  Applies for an input array of integer*4 values. Also returns an
      ! array of indexes sorted for increasing order of X which can used in
      ! GI4_SORT to reorder other arrays
      ! ---
      !  This version for I*8 indices
      !---------------------------------------------------------------------
      integer(kind=8), intent(in)    :: n      ! Length of arrays
      integer(kind=4), intent(inout) :: x(n)   ! Unsorted array
      integer(kind=8), intent(out)   :: it(n)  ! Integer array of sorted indexes
      logical,         intent(out)   :: error  ! Error flag
    end subroutine gi4_trie_i8
  end interface gi4_trie
  !
  interface gi8_trie
    subroutine gi8_trie_i4(x,it,n,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic gi8_trie
      !  Sorting program that uses a quicksort algorithm.
      !  Applies for an input array of integer*8 values. Also returns an
      ! array of indexes sorted for increasing order of X which can used in
      ! GI8_SORT to reorder other arrays
      ! ---
      !  This version for I*4 indices
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)    :: n      ! Length of arrays
      integer(kind=8), intent(inout) :: x(n)   ! Unsorted array
      integer(kind=4), intent(out)   :: it(n)  ! Integer array of sorted indexes
      logical,         intent(out)   :: error  ! Error flag
    end subroutine gi8_trie_i4
    subroutine gi8_trie_i8(x,it,n,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic gi8_trie
      !  Sorting program that uses a quicksort algorithm.
      !  Applies for an input array of integer*8 values. Also returns an
      ! array of indexes sorted for increasing order of X which can used in
      ! GI8_SORT to reorder other arrays
      ! ---
      !  This version for I*8 indices
      !---------------------------------------------------------------------
      integer(kind=8), intent(in)    :: n      ! Length of arrays
      integer(kind=8), intent(inout) :: x(n)   ! Unsorted array
      integer(kind=8), intent(out)   :: it(n)  ! Integer array of sorted indexes
      logical,         intent(out)   :: error  ! Error flag
    end subroutine gi8_trie_i8
  end interface gi8_trie
  !
  interface gr4_trie
    subroutine gr4_trie_i4(x,it,n,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic gr4_trie
      !  Sorting program that uses a quicksort algorithm.
      !  Applies for an input array of real*4 values. Also returns an array
      ! of indexes sorted for increasing order of X which can used in
      ! GR4_SORT to reorder other arrays
      ! ---
      !  This version for I*4 indices
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)    :: n      !
      real(kind=4),    intent(inout) :: x(n)   !
      integer(kind=4), intent(out)   :: it(n)  !
      logical,         intent(out)   :: error  !
    end subroutine gr4_trie_i4
    subroutine gr4_trie_i8(x,it,n,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic gr4_trie
      !  Sorting program that uses a quicksort algorithm.
      !  Applies for an input array of real*4 values. Also returns an array
      ! of indexes sorted for increasing order of X which can used in
      ! GR4_SORT to reorder other arrays
      ! ---
      !  This version for I*8 indices
      !---------------------------------------------------------------------
      integer(kind=8), intent(in)    :: n      !
      real(kind=4),    intent(inout) :: x(n)   !
      integer(kind=8), intent(out)   :: it(n)  !
      logical,         intent(out)   :: error  !
    end subroutine gr4_trie_i8
  end interface gr4_trie
  !
  interface gr8_trie
    subroutine gr8_trie_i4(x,it,n,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic gr8_trie
      !  Sorting program that uses a quicksort algorithm.
      ! Applies for an input array of real*8 values. Also returns an array
      ! of indexes sorted for increasing order of X which can used in
      ! GR8_SORT to reorder other arrays
      ! ---
      !  This version for I*4 indices
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)    :: n      ! Length of arrays
      real(kind=8),    intent(inout) :: x(n)   ! Unsorted array
      integer(kind=4), intent(out)   :: it(n)  ! Integer array of sorted indexes
      logical,         intent(out)   :: error  ! Error flag
    end subroutine gr8_trie_i4
    subroutine gr8_trie_i8(x,it,n,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public-generic gr8_trie
      !  Sorting program that uses a quicksort algorithm.
      ! Applies for an input array of real*8 values. Also returns an array
      ! of indexes sorted for increasing order of X which can used in
      ! GR8_SORT to reorder other arrays
      ! ---
      !  This version for I*8 indices
      !---------------------------------------------------------------------
      integer(kind=8), intent(in)    :: n      ! Length of arrays
      real(kind=8),    intent(inout) :: x(n)   ! Unsorted array
      integer(kind=8), intent(out)   :: it(n)  ! Integer array of sorted indexes
      logical,         intent(out)   :: error  ! Error flag
    end subroutine gr8_trie_i8
  end interface gr8_trie
  !
  interface
    subroutine gmath_random_seed_init(error)
      !---------------------------------------------------------------------
      ! @ public
      !  Initialize the Fortran random seed. Should be called by interactive
      ! programs or tasks
      !  NB: the Fortran standard does not promise that calling
      ! RANDOM_SEED() without argument will reuse again and again the same
      ! seed. We use our own default, which is a random seed based on date
      ! and time
      !---------------------------------------------------------------------
      logical, intent(inout) :: error
    end subroutine gmath_random_seed_init
  end interface
  !
  interface
    subroutine gmath_random_seed_set(argum,error)
      !---------------------------------------------------------------------
      ! @ public
      ! (Re)set the Fortran random seed, based on the input argument:
      !  - "DATETIME": based on current date and time
      !  - "URANDOM":  based on the OS /dev/urandom, if any
      !  - "Value":    caller choice
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: argum  !
      logical,          intent(inout) :: error  !
    end subroutine gmath_random_seed_set
  end interface
  !
  interface
    function rangau(sigma)
      !---------------------------------------------------------------------
      ! @ public
      ! Normal gaussian distribution with R.M.S. equal to sigma
      ! Version 1.1 8-jun-83
      ! Algorithm from Handbook of mathematical functions
      ! Ed. Abramowitz M. and Stegun I. A. , 26.2.23 (page 933)
      !---------------------------------------------------------------------
      real(kind=4) :: rangau  !
      real(kind=4), intent(in) :: sigma  !
    end function rangau
  end interface
  !
  interface
    function gag_random()
      !---------------------------------------------------------------------
      ! @ public
      !---------------------------------------------------------------------
      real(kind=4) :: gag_random              !
    end function gag_random
  end interface
  !
  interface
    function d_noise(a)
      !---------------------------------------------------------------------
      ! @ public
      ! Double precision version
      !---------------------------------------------------------------------
      real(kind=8) :: d_noise                 !
      real(kind=8), intent(in) :: a           !
    end function d_noise
  end interface
  !
  interface
    function d_random(a)
      !---------------------------------------------------------------------
      ! @ public
      ! Double precision version
      !---------------------------------------------------------------------
      real(kind=8) :: d_random                !
      real(kind=8), intent(in) :: a           !
    end function d_random
  end interface
  !
  interface
    function s_noise(a)
      !---------------------------------------------------------------------
      ! @ public
      ! Single precision version
      !---------------------------------------------------------------------
      real(kind=4) :: s_noise                 !
      real(kind=4), intent(in) :: a           !
    end function s_noise
  end interface
  !
  interface
    function s_random(a)
      !---------------------------------------------------------------------
      ! @ public
      ! Single precision version
      !---------------------------------------------------------------------
      real(kind=4) :: s_random                !
      real(kind=4), intent(in) :: a           !
    end function s_random
  end interface
  !
  interface
    subroutine transpose_getcode(strin,strout,code,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      !  Convert a dimension string into a transposition code, e.g.
      !   'VLM' transposed to 'LMV'  <=>  transposition code '231'
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: strin   !
      character(len=*), intent(in)    :: strout  !
      character(len=*), intent(out)   :: code    !
      logical,          intent(inout) :: error   !
    end subroutine transpose_getcode
  end interface
  !
  interface
    subroutine transpose_getorder(code,itr,mdims,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! Decode transposition code into an index of axis orders
      !---------------------------------------------------------------------
      character(len=*), intent(in)    :: code        ! Transposition code
      integer(kind=4),  intent(in)    :: mdims       ! Maximum number of dimensions
      integer(kind=4),  intent(out)   :: itr(mdims)  ! Transposition index array
      logical,          intent(inout) :: error       ! Error flag
    end subroutine transpose_getorder
  end interface
  !
  interface
    subroutine transpose_getblock(idim,ndims,code,block,error)
      use gildas_def
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      !  Repack the transposition order into a general case of the following form:
      !      unchanged, swap1,  unchanged, swap2,   unchanged
      !      Nelems,    Nfirst, Nmiddle,   Nsecond, Nlast
      !---------------------------------------------------------------------
      integer(kind=4),            intent(in)    :: ndims        ! Effective or maximum number of dimensions
      integer(kind=index_length), intent(in)    :: idim(ndims)  ! Array dimensions
      character(len=*),           intent(in)    :: code         ! Transposition code
      integer(kind=index_length), intent(out)   :: block(5)     ! Resulting transposition pack
      logical,                    intent(inout) :: error        ! Error flag
    end subroutine transpose_getblock
  end interface
  !
  interface
    subroutine trans4all(x,y,nb,n1,nm,n2,nl)
      use gildas_def
      !---------------------------------------------------------------------
      ! @ public-mandatory (because symbol is used elsewhere)
      ! Swap the 2nd and 4th dimension among the 5 ones.
      ! This version for 4-bytes words.
      !---------------------------------------------------------------------
      integer(kind=index_length), intent(in)  :: nb                 !
      integer(kind=index_length), intent(in)  :: n1                 !
      integer(kind=index_length), intent(in)  :: nm                 !
      integer(kind=index_length), intent(in)  :: n2                 !
      integer(kind=index_length), intent(in)  :: nl                 !
      real(kind=4),               intent(out) :: x(nb,n2,nm,n1,nl)  !
      real(kind=4),               intent(in)  :: y(nb,n1,nm,n2,nl)  !
    end subroutine trans4all
  end interface
  !
  interface
    subroutine trans4(in,ou,nelems,nx,nm,ny)
      use gildas_def
      !---------------------------------------------------------------------
      ! @ public
      ! Swap the 2nd and 4th dimension among the 4 ones.
      ! This version for 4-bytes words.
      !---------------------------------------------------------------------
      integer(kind=index_length), intent(in)  :: nelems               !
      integer(kind=index_length), intent(in)  :: nx                   !
      integer(kind=index_length), intent(in)  :: nm                   !
      integer(kind=index_length), intent(in)  :: ny                   !
      real(kind=4),               intent(in)  :: in(nelems,nx,nm,ny)  !
      real(kind=4),               intent(out) :: ou(nelems,ny,nm,nx)  !
    end subroutine trans4
  end interface
  !
  interface
    subroutine trans4slice(nelems,nfirst,nmiddl,nsecon,in,kin,lin,ou,kou,lou)
      use gildas_def
      !---------------------------------------------------------------------
      ! @ public
      ! Swap the 2nd and 4th dimension among the 4 ones, for the slices
      ! [kin:lin] in 'nsecon' and [kou:lou] in 'nfirst'.
      ! This version for 4-bytes words.
      !---------------------------------------------------------------------
      integer(kind=index_length), intent(in)  :: nelems                      !
      integer(kind=index_length), intent(in)  :: nfirst                      !
      integer(kind=index_length), intent(in)  :: nmiddl                      !
      integer(kind=index_length), intent(in)  :: nsecon                      !
      integer(kind=index_length), intent(in)  :: kin,lin                     !
      integer(kind=index_length), intent(in)  :: kou,lou                     !
      real(kind=4),               intent(in)  :: in(nelems,nfirst,nmiddl,*)  !
      real(kind=4),               intent(out) :: ou(nelems,nsecon,nmiddl,*)  !
    end subroutine trans4slice
  end interface
  !
  interface
    subroutine trans8all(x,y,nb,n1,nm,n2,nl)
      use gildas_def
      !---------------------------------------------------------------------
      ! @ public-mandatory (because symbol is used elsewhere)
      ! Swap the 2nd and 4th dimension among the 5 ones.
      ! This version for 8-bytes words.
      !---------------------------------------------------------------------
      integer(kind=index_length), intent(in)  :: nb                 !
      integer(kind=index_length), intent(in)  :: n1                 !
      integer(kind=index_length), intent(in)  :: nm                 !
      integer(kind=index_length), intent(in)  :: n2                 !
      integer(kind=index_length), intent(in)  :: nl                 !
      real(kind=8),               intent(out) :: x(nb,n2,nm,n1,nl)  !
      real(kind=8),               intent(in)  :: y(nb,n1,nm,n2,nl)  !
    end subroutine trans8all
  end interface
  !
  interface
    subroutine gwavelet_subtract(iorder,wavelets,vec,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! Subtract the ith order when asked
      !---------------------------------------------------------------------
      integer(kind=4), intent(in)    :: iorder 
      real(kind=4),    intent(in)    :: wavelets(:,:)
      real(kind=4),    intent(inout) :: vec(:)
      logical,         intent(inout) :: error
    end subroutine gwavelet_subtract
  end interface
  !
  interface
    subroutine gwavelet_gaps(vec1,wavelets1,error)
      use gbl_message
      !---------------------------------------------------------------------
      ! @ public
      ! Compute the wavelets for an input 1D data
      ! Take care of edge effects by mirroring the vector at each edge
      ! On return the input 'wavelets' array has been allocated and filled
      !---------------------------------------------------------------------
      real(kind=4),              intent(in)    :: vec1(:)        ! Data
      real(kind=4), allocatable, intent(inout) :: wavelets1(:,:) ! Results
      logical,                   intent(inout) :: error          ! Logical error flag
    end subroutine gwavelet_gaps
  end interface
  !
end module gmath_interfaces_public
