module hecmw_metis_5
  use, intrinsic :: iso_c_binding !, only : C_int, C_double, C_float
  implicit none
  integer,parameter :: idx_t  = c_int
  integer,parameter :: real_t = c_float

  integer,parameter :: METIS_OK              = 1   !< Returned normally */
  integer,parameter :: METIS_ERROR_INPUT     = -2  !< Returned due to erroneous inputs and/or options */
  integer,parameter :: METIS_ERROR_MEMORY    = -3  !< Returned due to insufficient memory */
  integer,parameter :: METIS_ERROR           = -4  !< Some other errors */

  integer,parameter :: METIS_ERROR_SETUP     = -11 !< Returned due to setup data contradiction for METIS5
  integer,parameter :: METIS_ERROR_SUPERVERTEX = -12 !< Returned due to error inputs of super vertices for extension functions

  integer,parameter :: METIS_TYPE_PartGraphRecursive   = 1
  integer,parameter :: METIS_TYPE_mCPartGraphRecursive = 2
  integer,parameter :: METIS_TYPE_WPartGraphRecursive  = 3

  integer,parameter :: METIS_TYPE_PartGraphKway        = 1
  integer,parameter :: METIS_TYPE_PartGraphVKway       = 2
  integer,parameter :: METIS_TYPE_mCPartGraphKway      = 3
  integer,parameter :: METIS_TYPE_WPartGraphKway       = 4
  integer,parameter :: METIS_TYPE_WPartGraphVKway      = 5

  interface
    function METIS_NodeND_f (nvtxs, xadj, adjncy, vwgt, options, perm, iperm) &
      result(ierr) bind(C, name="METIS_NodeND")
      import
      integer(idx_t)             :: ierr
      integer(idx_t), intent(in) :: nvtxs
      type(c_ptr), value         :: xadj,adjncy
      type(c_ptr), value         :: vwgt
      type(c_ptr), value         :: options
      type(c_ptr), value         :: perm
      type(c_ptr), value         :: iperm
    end function METIS_NodeND_f
  end interface
contains

  function hecmw_METIS_NodeND (nvtxs, xadj, adjncy, vwgt, options, perm, iperm) result(ierr)
    integer(idx_t) :: ierr
    integer(idx_t) :: nvtxs
    integer(idx_t), pointer :: xadj(:)
    integer(idx_t), pointer :: adjncy(:)
    integer(idx_t), pointer :: options(:)
    integer(idx_t), pointer :: vwgt(:)
    integer(idx_t), pointer :: perm(:)
    integer(idx_t), pointer :: iperm(:)

    type(c_ptr) :: xadj_ptr, adjncy_ptr, vwgt_ptr
    type(c_ptr) :: options_ptr
    type(c_ptr) :: perm_ptr
    type(c_ptr) :: iperm_ptr

    if(associated(xadj)) then
      xadj_ptr  = c_loc(xadj(1))
    else
      xadj_ptr  = c_null_ptr
    endif
    if(associated(adjncy)) then
      adjncy_ptr  = c_loc(adjncy(1))
    else
      adjncy_ptr  = c_null_ptr
    endif
    if(associated(vwgt)) then
      vwgt_ptr  = c_loc(vwgt(1))
    else
      vwgt_ptr  = c_null_ptr
    endif
    if(associated(options)) then
      options_ptr = c_loc(options(1))
    else
      options_ptr = c_null_ptr
    endif
    if(associated(perm)) then
      perm_ptr   = c_loc(perm(1))
    else
      perm_ptr   = c_null_ptr
    endif
    if(associated(iperm)) then
      iperm_ptr  = c_loc(iperm(1))
    else
      iperm_ptr  = c_null_ptr
    endif

    ierr = METIS_NodeND_f(nvtxs, xadj_ptr, adjncy_ptr, vwgt_ptr, options_ptr, perm_ptr, iperm_ptr)
  end function hecmw_METIS_NodeND

end module hecmw_metis_5
