Skip to content

Commit 38ebcd0

Browse files
committed
Added support for complex numbers in loadtxt and savetxt
1 parent eeb33d7 commit 38ebcd0

File tree

3 files changed

+72
-17
lines changed

3 files changed

+72
-17
lines changed

src/common.fypp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@
99
#! Collected (kind, type) tuples for real types
1010
#:set REAL_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES))
1111

12+
#! Complex kinds to be considered during templating
13+
#:set CMPLX_KINDS = ["sp", "dp", "qp"]
14+
15+
#! Complex types to be considere during templating
16+
#:set CMPLX_TYPES = ["complex({})".format(k) for k in CMPLX_KINDS]
17+
18+
#! Collected (kind, type) tuples for complex types
19+
#:set CMPLX_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES))
1220

1321
#! Integer kinds to be considered during templating
1422
#:set INT_KINDS = ["int8", "int16", "int32", "int64"]

src/stdlib_experimental_io.fypp

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#:include "common.fypp"
22

3-
#:set KINDS_TYPES = REAL_KINDS_TYPES + INT_KINDS_TYPES
3+
#:set KINDS_TYPES = REAL_KINDS_TYPES + INT_KINDS_TYPES + CMPLX_KINDS_TYPES
44

55
module stdlib_experimental_io
66

@@ -18,21 +18,22 @@ module stdlib_experimental_io
1818
public :: parse_mode
1919

2020
interface loadtxt
21-
#:for k1, _ in KINDS_TYPES
22-
module procedure loadtxt_${k1}$
21+
#:for k1, t1 in KINDS_TYPES
22+
module procedure loadtxt_${t1[0]}$${k1}$
23+
! loadtxt_${k1}$
2324
#:endfor
2425
end interface loadtxt
2526

2627
interface savetxt
27-
#:for k1, _ in KINDS_TYPES
28-
module procedure savetxt_${k1}$
28+
#:for k1, t1 in KINDS_TYPES
29+
module procedure savetxt_${t1[0]}$${k1}$
2930
#:endfor
3031
end interface
3132

3233
contains
3334

3435
#:for k1, t1 in KINDS_TYPES
35-
subroutine loadtxt_${k1}$(filename, d)
36+
subroutine loadtxt_${t1[0]}$${k1}$(filename, d)
3637
! Loads a 2D array from a text file.
3738
!
3839
! Arguments
@@ -74,12 +75,12 @@ contains
7475
end do
7576
close(s)
7677

77-
end subroutine loadtxt_${k1}$
78+
end subroutine loadtxt_${t1[0]}$${k1}$
7879
#:endfor
7980

8081

8182
#:for k1, t1 in KINDS_TYPES
82-
subroutine savetxt_${k1}$(filename, d)
83+
subroutine savetxt_${t1[0]}$${k1}$(filename, d)
8384
! Saves a 2D array into a text file.
8485
!
8586
! Arguments
@@ -100,7 +101,7 @@ contains
100101
write(s, *) d(i, :)
101102
end do
102103
close(s)
103-
end subroutine savetxt_${k1}$
104+
end subroutine savetxt_${t1[0]}$${k1}$
104105
#:endfor
105106

106107

@@ -126,23 +127,33 @@ contains
126127
end function number_of_columns
127128

128129

129-
integer function number_of_rows_numeric(s)
130+
integer function number_of_rows_numeric(s) result(nrows)
130131
! determine number or rows
131132
integer,intent(in)::s
132133
integer :: ios
133134

134-
real::r
135+
real :: r
136+
complex :: z
135137

136138
rewind(s)
137-
number_of_rows_numeric = 0
139+
nrows = 0
138140
do
139141
read(s, *, iostat=ios) r
140142
if (ios /= 0) exit
141-
number_of_rows_numeric = number_of_rows_numeric + 1
143+
nrows = nrows + 1
142144
end do
143145

144146
rewind(s)
145147

148+
! If there are no rows of real numbers, it may be that they are complex
149+
if( nrows == 0) then
150+
do
151+
read(s, *, iostat=ios) z
152+
if (ios /= 0) exit
153+
nrows = nrows + 1
154+
end do
155+
rewind(s)
156+
end if
146157
end function number_of_rows_numeric
147158

148159

src/tests/io/test_savetxt.f90

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ program test_savetxt
99
outpath = get_outpath() // "/tmp.dat"
1010

1111
call test_int32(outpath)
12-
call test_sp(outpath)
13-
call test_dp(outpath)
12+
call test_rsp(outpath)
13+
call test_rdp(outpath)
14+
call test_csp(outpath)
15+
call test_cdp(outpath)
1416

1517
contains
1618

@@ -45,7 +47,7 @@ subroutine test_int32(outpath)
4547
end subroutine
4648

4749

48-
subroutine test_sp(outpath)
50+
subroutine test_rsp(outpath)
4951
character(*), intent(in) :: outpath
5052
real(sp) :: d(3, 2), e(2, 3)
5153
real(sp), allocatable :: d2(:, :)
@@ -63,7 +65,7 @@ subroutine test_sp(outpath)
6365
end subroutine
6466

6567

66-
subroutine test_dp(outpath)
68+
subroutine test_rdp(outpath)
6769
character(*), intent(in) :: outpath
6870
real(dp) :: d(3, 2), e(2, 3)
6971
real(dp), allocatable :: d2(:, :)
@@ -80,4 +82,38 @@ subroutine test_dp(outpath)
8082
call assert(all(abs(e-d2) < epsilon(1._dp)))
8183
end subroutine
8284

85+
subroutine test_csp(outpath)
86+
character(*), intent(in) :: outpath
87+
complex(sp) :: d(3, 2), e(2, 3)
88+
complex(sp), allocatable :: d2(:, :)
89+
d = cmplx(1, 1)* reshape([1, 2, 3, 4, 5, 6], [3, 2])
90+
call savetxt(outpath, d)
91+
call loadtxt(outpath, d2)
92+
call assert(all(shape(d2) == [3, 2]))
93+
call assert(all(abs(d-d2) < epsilon(1._sp)))
94+
95+
e = reshape([1, 2, 3, 4, 5, 6], [2, 3])
96+
call savetxt(outpath, e)
97+
call loadtxt(outpath, d2)
98+
call assert(all(shape(d2) == [2, 3]))
99+
call assert(all(abs(e-d2) < epsilon(1._sp)))
100+
end subroutine
101+
102+
subroutine test_cdp(outpath)
103+
character(*), intent(in) :: outpath
104+
complex(dp) :: d(3, 2), e(2, 3)
105+
complex(dp), allocatable :: d2(:, :)
106+
d = cmplx(1._dp, 1._dp)* reshape([1, 2, 3, 4, 5, 6], [3, 2])
107+
call savetxt(outpath, d)
108+
call loadtxt(outpath, d2)
109+
call assert(all(shape(d2) == [3, 2]))
110+
call assert(all(abs(d-d2) < epsilon(1._dp)))
111+
112+
e = reshape([1, 2, 3, 4, 5, 6], [2, 3])
113+
call savetxt(outpath, e)
114+
call loadtxt(outpath, d2)
115+
call assert(all(shape(d2) == [2, 3]))
116+
call assert(all(abs(e-d2) < epsilon(1._dp)))
117+
end subroutine
118+
83119
end program

0 commit comments

Comments
 (0)