Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
9301ba1
draft implementation
jalvesz Oct 11, 2025
e1fbad1
manage symmetric storages
jalvesz Oct 11, 2025
f7b4700
Merge branch 'matrix_market' of https://github.com/jalvesz/stdlib int…
jalvesz Oct 11, 2025
b6ba5cd
Merge branch 'fortran-lang:master' into matrix_market
jalvesz Oct 17, 2025
34e5a3c
Merge branch 'fortran-lang:master' into matrix_market
jalvesz Dec 11, 2025
0ea33f7
Merge branch 'fortran-lang:master' into matrix_market
jalvesz Dec 29, 2025
32b1df1
add examples and test
jalvesz Dec 31, 2025
08f8c6b
Merge branch 'fortran-lang:master' into matrix_market
jalvesz Jan 9, 2026
912f9ef
Merge branch 'matrix_market' of https://github.com/jalvesz/stdlib int…
jalvesz Jan 9, 2026
6a21d2a
split mm_save into dense and coo
jalvesz Jan 10, 2026
eac6f6b
Merge branch 'fortran-lang:master' into matrix_market
jalvesz Jan 13, 2026
2fb010f
added temporary arrays to read from mtx file for coordinate matrices …
Mahmood-Sinan Jan 13, 2026
621de46
fixed subroutine name typo, coordinate write format and store lower t…
Mahmood-Sinan Jan 15, 2026
44c1a74
Merge branch 'fortran-lang:master' into matrix_market
jalvesz Jan 16, 2026
7b78c6d
added deallocation of temp arrays while reading mtx, calculation of n…
Mahmood-Sinan Jan 19, 2026
7189b92
moved initialization of expand variable to a new line
Mahmood-Sinan Jan 20, 2026
694c0f3
changed COMPLEX() to cmplx() inside load function
Mahmood-Sinan Jan 22, 2026
3019722
Merge branch 'fortran-lang:master' into matrix_market
jalvesz Jan 22, 2026
a453ff3
Merge branch 'matrix_market' of https://github.com/jalvesz/stdlib int…
jalvesz Jan 23, 2026
4aa2fad
move files according to new folder structure
jalvesz Jan 23, 2026
a8d988a
changed from COO sparse matrix to plain arrays
Mahmood-Sinan Jan 26, 2026
c0351f3
add format specifier and integer subroutines for saving and loading
Mahmood-Sinan Jan 26, 2026
014b644
fix dependencies
jalvesz Jan 27, 2026
90a3ba5
Merge branch 'matrix_market' of https://github.com/jalvesz/stdlib int…
jalvesz Jan 27, 2026
8a9ffb9
Update src/io/stdlib_io_mm.fypp
jalvesz Jan 29, 2026
0c33205
Update example/io/example_matrix_market.f90
jalvesz Jan 29, 2026
53d3ac3
fix: filling of upper triangular half incase of loading dense symmtry…
Mahmood-Sinan Feb 2, 2026
a1ba8ac
add AUTO symmetry option for dense matrices
Mahmood-Sinan Feb 2, 2026
7cf80fc
add: error handling
Mahmood-Sinan Feb 20, 2026
2d02766
add: basic test_io_mm
Mahmood-Sinan Feb 20, 2026
28db893
add: test array general
Mahmood-Sinan Feb 21, 2026
be4c498
test_io_mm_array implemented
Mahmood-Sinan Feb 21, 2026
67a90c2
minor change
Mahmood-Sinan Feb 21, 2026
c736d41
add initialization of err variables to zero
Mahmood-Sinan Feb 22, 2026
8d505bb
modify test
Mahmood-Sinan Feb 22, 2026
63634be
minor changes
Mahmood-Sinan Feb 24, 2026
0bf7170
remove: unused constants dependency
Mahmood-Sinan Feb 24, 2026
e8e7387
Merge branch 'fortran-lang:master' into matrix_market
jalvesz Feb 26, 2026
5abdabd
minor changes to write mm header call
Mahmood-Sinan Mar 4, 2026
3113f13
add stat error check after each time reading an input value
Mahmood-Sinan Mar 4, 2026
c03119d
Merge remote-tracking branch 'upstream/master' into matrix_market
Mahmood-Sinan Mar 5, 2026
91fbede
add zero length array save condition for COO type
Mahmood-Sinan Mar 5, 2026
107ffda
added coo tests
Mahmood-Sinan Mar 6, 2026
213bc2a
remove I and made R one more dimensional
Mahmood-Sinan Mar 6, 2026
c1a8c65
change fypp to subroutine: dense done
Mahmood-Sinan Mar 7, 2026
a4cb00e
change fypp to subroutine: complete
Mahmood-Sinan Mar 7, 2026
4d220cc
modularized
Mahmood-Sinan Mar 7, 2026
4b27f8c
minor changes
Mahmood-Sinan Mar 7, 2026
ad02254
minor improvements and updated fisher algorithm
Mahmood-Sinan Mar 7, 2026
749b798
trim trailing whitespaces
Mahmood-Sinan Mar 7, 2026
4a65054
add: pattern support and tests
Mahmood-Sinan Mar 9, 2026
64456f5
Merge branch 'fortran-lang:master' into matrix_market
jalvesz Mar 13, 2026
3183c37
delet file
jalvesz Mar 13, 2026
874bad2
modify: remove pattern test duplication
Mahmood-Sinan Mar 14, 2026
e00ee73
move optional arguments to last inside mm_fail_process declaration
Mahmood-Sinan Mar 14, 2026
476cdf6
Merge branch 'fortran-lang:master' into matrix_market
jalvesz Mar 15, 2026
13df893
Merge branch 'fortran-lang:master' into matrix_market
jalvesz Mar 27, 2026
9353e2e
Merge branch 'fortran-lang:master' into matrix_market
jalvesz Apr 2, 2026
bfd3bcc
fix: while loop in comments part
Mahmood-Sinan Apr 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions doc/specs/stdlib_io.md
Original file line number Diff line number Diff line change
Expand Up @@ -305,3 +305,70 @@ Exceptions trigger an `error stop` unless the optional `err` argument is provide
{!example/io/example_get_file.f90!}
```

## Matrix Market Format I/O

### Status

Experimental

### Description

The Matrix Market I/O module provides support for reading and writing matrices in the Matrix Market format, a simple ASCII format for sparse and dense matrices developed at NIST. The format supports real, complex, and integer matrices with various symmetry properties.

### `load_mm` - load a matrix from Matrix Market file

#### Syntax

`call ` [[stdlib_io_mm(module):load_mm(interface)]] `(filename, matrix [, iostat] [, iomsg])`

#### Arguments

`filename`: Shall be a character expression containing the Matrix Market file name to read from.

`matrix`: Shall be an allocatable rank-2 array of type `real`, `complex`, or `integer` that will contain the loaded matrix.

`iostat` (optional): Shall be a scalar of type `integer` that receives the error status. Zero indicates success.

`iomsg` (optional): Shall be an allocatable character string that receives the error message if iostat is non-zero.

#### Description

Loads a 2D matrix from a Matrix Market format file. The routine automatically detects the data type, format (coordinate or array), and symmetry properties from the file header. For coordinate format files, symmetric matrices are expanded to full storage.

### `save_mm` - save a matrix to Matrix Market file

#### Syntax

`call ` [[stdlib_io_mm(module):save_mm(interface)]] `(filename, matrix [, header_info] [, iostat] [, iomsg])`

#### Arguments

`filename`: Shall be a character expression containing the Matrix Market file name to write to.

`matrix`: Shall be a rank-2 array of type `real`, `complex`, or `integer` to save.

`header_info` (optional): Shall be a character expression containing additional comments for the file header. Can also specify format preference ('coordinate' or 'array').

`iostat` (optional): Shall be a scalar of type `integer` that receives the error status. Zero indicates success.

`iomsg` (optional): Shall be an allocatable character string that receives the error message if iostat is non-zero.

#### Description

Saves a 2D matrix to Matrix Market format file. The routine automatically chooses coordinate format for sparse matrices (< 50% non-zero) and array format for dense matrices, unless overridden in `header_info`.
Comment on lines +318 to +358
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation only describes the dense matrix interface for load_mm and save_mm, but doesn't document the sparse (COO) interface that accepts separate index and data parameters. The COO interface should be documented as an alternative syntax for loading and saving sparse matrices.

Copilot uses AI. Check for mistakes.
Comment on lines +342 to +358
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation describes a parameter called header_info on lines 342 and 350, but the actual interface uses three separate optional parameters: comment, format, and symmetry. The documentation should be updated to match the actual API. Additionally, line 358 mentions automatic format selection based on sparsity, but this feature is not implemented in the current code.

Copilot uses AI. Check for mistakes.

### Matrix Market Format Details

The Matrix Market format supports:

- **Object types**: Currently only `matrix` is supported
- **Formats**: `coordinate` (sparse) and `array` (dense)
- **Data types**: `real`, `complex`, `integer` (pattern not yet supported)
- **Symmetry**: `general`, `symmetric`, `skew-symmetric`, `hermitian`

### Example

```fortran
{!example/io/example_matrix_market.f90!}
```

1 change: 1 addition & 0 deletions example/io/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ ADD_EXAMPLE(fmt_constants)
ADD_EXAMPLE(get_file)
ADD_EXAMPLE(loadnpy)
ADD_EXAMPLE(loadtxt)
ADD_EXAMPLE(matrix_market)
ADD_EXAMPLE(open)
ADD_EXAMPLE(savenpy)
ADD_EXAMPLE(savetxt)
93 changes: 93 additions & 0 deletions example/io/example_matrix_market.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
program example_matrix_market
use stdlib_io_mm, only : load_mm, save_mm
use stdlib_kinds, only : dp
implicit none

real(dp), allocatable :: matrix(:,:), matrix2(:,:)
integer, allocatable :: index(:,:)
real(dp), allocatable :: data(:)
character(len=*), parameter :: dense_filename = "test_dense.mtx"
character(len=*), parameter :: sparse_filename = "test_sparse.mtx"
integer :: iostat, i
character(len=:), allocatable :: iomsg

iostat = 0
iomsg = ''
! Create a test dense matrix
allocate(matrix(3,3))
matrix = reshape([1.0_dp, 2.0_dp, 3.0_dp, &
4.0_dp, 5.0_dp, 6.0_dp, &
7.0_dp, 8.0_dp, 9.0_dp], [3,3])

print *, "=== Dense Matrix Example ==="
print *, "Original dense matrix:"
call print_matrix(matrix)

! Save dense matrix to Matrix Market file
call save_mm(dense_filename, matrix, iostat=iostat, iomsg=iomsg)
if (iostat /= 0) then
print *, "Error saving dense matrix: ", iomsg
stop 1
end if

print *, "Dense matrix saved to ", dense_filename

! Load dense matrix from Matrix Market file
call load_mm(dense_filename, matrix2, iostat=iostat, iomsg=iomsg)
if (iostat /= 0) then
print *, "Error loading dense matrix: ", iomsg
stop 1
end if

print *, "Loaded dense matrix:"
call print_matrix(matrix2)

! Create a sparse test file manually for demonstration
call create_sparse_test_file(sparse_filename)

print *, "=== Sparse Matrix Example ==="
print *, "Loading sparse matrix from ", sparse_filename

! Load sparse matrix from Matrix Market file
call load_mm(sparse_filename, index, data, iostat=iostat, iomsg=iomsg)
if (iostat /= 0) then
print *, "Error loading sparse matrix: ", iomsg
stop 1
end if

print *, "Loaded sparse matrix (COO format):"
print *, "Data (row, col, value):"
do i = 1, size(data)
print *, index(1,i), index(2,i), data(i)
end do

contains

subroutine print_matrix(mat)
real(dp), intent(in) :: mat(:,:)
integer :: i

do i = 1, size(mat, 1)
print *, mat(i, :)
end do
print *
end subroutine print_matrix

subroutine create_sparse_test_file(filename)
character(len=*), intent(in) :: filename
integer :: u

open(newunit=u, file=filename, status='replace')
write(u, '(A)') '%%MatrixMarket matrix coordinate real general'
write(u, '(A)') '% This is a test sparse matrix'
write(u, '(A)') '4 4 6'
write(u, '(A)') '1 1 10.0'
write(u, '(A)') '2 2 20.0'
write(u, '(A)') '3 3 30.0'
write(u, '(A)') '4 4 40.0'
write(u, '(A)') '1 4 5.0'
write(u, '(A)') '3 1 15.0'
close(u)
end subroutine create_sparse_test_file

end program example_matrix_market
3 changes: 3 additions & 0 deletions src/io/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ set(io_fppFiles
stdlib_io_npy.fypp
stdlib_io_npy_load.fypp
stdlib_io_npy_save.fypp
stdlib_io_mm.fypp
stdlib_io_mm_load.fypp
stdlib_io_mm_save.fypp
)

set(io_cppFiles
Expand Down
94 changes: 94 additions & 0 deletions src/io/stdlib_io_mm.fypp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
! 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
Loading
Loading