Is there a public domain subroutine that reads a real matrix of arbitrary size from a text file? I can write one but would probably be reinventing the wheel. R and Python with Pandas have more general functions to read data frames.

My program which calls a subroutine to read a matrix with a fixed number of columns, optionally with column labels, is

```
module kind_mod
implicit none
private
public :: dp
integer, parameter :: dp = kind(1.0d0)
end module kind_mod
!
module read_matrix_alloc_mod
use kind_mod, only: dp
implicit none
private
public :: read_mat_real
contains
subroutine read_mat_real(xfile,ncol,xx,col_labels,max_rows)
! read from xfile matrix xx(:,:) and optionally column labels
character (len=*), intent(in) :: xfile
integer , intent(in) :: ncol
real(kind=dp) , intent(out), allocatable :: xx(:,:)
character (len=*), intent(out), optional :: col_labels(:)
integer , intent(in) , optional :: max_rows
real(kind=dp) , allocatable :: xcp(:,:)
integer :: i,ierr,ierr_read,iu,max_rows_,nrows
character (len=10000) :: text
character (len=*), parameter :: msg="in read_matrix_alloc_mod::read_mat_real, "
if (present(col_labels)) then
if (size(col_labels) /= ncol) then
write (*,*) msg,"ncol, size(col_labels) =",ncol,size(col_labels)," must be equal, STOPPING"
stop
end if
end if
if (present(max_rows)) then
max_rows_ = max_rows
else
max_rows_ = 100000
end if
open (newunit=iu,file=xfile,action="read")
if (present(col_labels)) then
read (iu,"(a)",iostat=ierr_read) text
read (text,*,iostat=ierr) col_labels
if (ierr /= 0) then
write (*,*) msg,"could not read ",size(col_labels)," words from '" // &
trim(text) // "', STOPPING"
stop
end if
end if
allocate (xx(max_rows_,ncol))
nrows = max_rows_
i = 0
do
read (iu,"(a)",iostat=ierr_read) text
if (ierr_read /= 0) then
nrows = i
exit
end if
i = i + 1
if (i > max_rows_) exit
read (text,*,iostat=ierr_read) xx(i,:)
if (ierr_read /= 0) then
backspace(iu)
nrows = i-1
exit
end if
end do
allocate (xcp(nrows,ncol))
xcp = xx(:nrows,:)
deallocate (xx)
allocate (xx(nrows,ncol))
xx = xcp
deallocate (xcp)
end subroutine read_mat_real
end module read_matrix_alloc_mod
!
program xread_mat_real
use kind_mod , only: dp
use read_matrix_alloc_mod, only: read_mat_real
integer :: i
integer , parameter :: ncol = 2
real(kind=dp) , allocatable :: xx(:,:)
character (len=20), allocatable :: col_labels(:)
allocate (col_labels(ncol))
call read_mat_real("xsquares.csv",ncol,xx,col_labels)
write (*,"(100a10)") (trim(col_labels(i)),i=1,size(col_labels))
do i=1,size(xx,1)
write (*,"(100f10.4)") xx(i,:)
end do
end program xread_mat_real
```

which for file xsquares.csv

```
x,x^2
2.0,4.0
2.5,6.25
1.5,2.25
```

gives output

```
x x^2
2.0000 4.0000
2.5000 6.2500
1.5000 2.2500
```