! SPDX-Identifier: MIT

#:include "common.fypp"
#:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX))
#:set C_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_SUFFIX))
#:set I_KINDS_TYPES  = list(zip(INT_KINDS,   INT_TYPES, INT_KINDS))
#:set RCI_KINDS_TYPES = R_KINDS_TYPES + C_KINDS_TYPES + I_KINDS_TYPES

!> The Matrix Market (MM) format is a simple, human-readable, ASCII format for sparse
!> and dense matrices. The format was developed at NIST (National Institute of Standards
!> and Technology) for the Matrix Market, a repository of test matrices for use in
!> comparative studies of algorithms for numerical linear algebra.
!>
!> For more information, see: https://math.nist.gov/MatrixMarket/formats.html
module stdlib_io_mm
    use stdlib_kinds, only : int8, int16, int32, int64, sp, dp, xdp, qp
    implicit none
    private

    type, public :: mm_header_type
        integer :: object
        integer :: format
        integer :: qualifier
        integer :: symmetry
        character(len=1024), allocatable :: comments(:)
    end type mm_header_type

    !> Version: experimental
    !>
    !> Load a matrix from a Matrix Market file
    !> ([Specification](../page/specs/stdlib_io.html#load_mm))
    interface load_mm
        #:for k, t, s in RCI_KINDS_TYPES
        module subroutine load_mm_dense_${s}$(filename, matrix, iostat, iomsg)
            !> Name of the Matrix Market file to load from
            character(len=*), intent(in) :: filename
            !> Matrix to be loaded from the Matrix Market file
            ${t}$, allocatable, intent(out) :: matrix(:,:)
            !> Error status of loading, zero on success
            integer, intent(out), optional :: iostat
            !> Associated error message in case of non-zero status code
            character(len=:), allocatable, intent(out), optional :: iomsg
        end subroutine
        #:endfor
        #:for k, t, s in RCI_KINDS_TYPES
        module subroutine load_mm_coo_${s}$(filename, index, data, iostat, iomsg)
            !> Name of the Matrix Market file to load from
            character(len=*), intent(in) :: filename
            !> Matrix indices to be read from the Matrix Market file
            integer, allocatable, intent(out) :: index(:,:)
            !> Matrix data to be read from the Matrix Market file
            ${t}$, allocatable, intent(out) :: data(:)
            !> Error status of loading, zero on success
            integer, intent(out), optional :: iostat
            !> Associated error message in case of non-zero status code
            character(len=:), allocatable, intent(out), optional :: iomsg
        end subroutine
        #:endfor
    end interface
    public :: load_mm

    !> Version: experimental
    !>
    !> Save a matrix to a Matrix Market file
    !> ([Specification](../page/specs/stdlib_io.html#save_mm))
    interface save_mm
        #:for k, t, s in RCI_KINDS_TYPES
        module subroutine save_mm_dense_${s}$(filename, matrix, comment, format, symmetry, iostat, iomsg)
        character(len=*), intent(in) :: filename
        ${t}$, intent(in) :: matrix(:,:)
        character(len=*), intent(in), optional :: comment
        character(len=*), intent(in), optional :: format
        character(len=*), intent(in), optional :: symmetry
        integer, intent(out), optional :: iostat
        character(len=:), allocatable, intent(out), optional :: iomsg
        end subroutine
        #:endfor

        #:for k, t, s in RCI_KINDS_TYPES
        module subroutine save_mm_coo_${s}$(filename, index, data, comment, format, symmetry, iostat, iomsg)
        character(len=*), intent(in) :: filename
        integer, intent(in) :: index(:,:)
        ${t}$, intent(in) :: data(:)
        character(len=*), intent(in), optional :: comment
        character(len=*), intent(in), optional :: format
        character(len=*), intent(in), optional :: symmetry
        integer, intent(out), optional :: iostat
        character(len=:), allocatable, intent(out), optional :: iomsg
        end subroutine
        #:endfor
    end interface save_mm
    public :: save_mm

end module stdlib_io_mm