Skip to content

Commit 5186134

Browse files
authored
Merge pull request #37 from jvdp1/loadtxt2
Single and quadruple precisions for load/savetxt
2 parents ae5591f + a19832e commit 5186134

File tree

3 files changed

+217
-33
lines changed

3 files changed

+217
-33
lines changed

src/stdlib_experimental_io.f90

+170-28
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,64 @@
11
module stdlib_experimental_io
2-
use iso_fortran_env, only: sp=>real32, dp=>real64
2+
use iso_fortran_env, only: sp=>real32, dp=>real64, qp=>real128
33
implicit none
44
private
55
public :: loadtxt, savetxt
66

77
interface loadtxt
88
module procedure sloadtxt
99
module procedure dloadtxt
10+
module procedure qloadtxt
1011
end interface
1112

1213
interface savetxt
1314
module procedure ssavetxt
1415
module procedure dsavetxt
16+
module procedure qsavetxt
1517
end interface
1618

1719
contains
1820

1921
subroutine sloadtxt(filename, d)
22+
! Loads a 2D array from a text file.
23+
!
24+
! Arguments
25+
! ---------
26+
!
27+
! Filename to load the array from
2028
character(len=*), intent(in) :: filename
29+
! The array 'd' will be automatically allocated with the correct dimensions
2130
real(sp), allocatable, intent(out) :: d(:,:)
22-
real(dp), allocatable :: tmp(:,:)
23-
call dloadtxt(filename, tmp)
24-
allocate(d(size(tmp,1),size(tmp,2)))
25-
d = real(tmp,sp)
31+
!
32+
! Example
33+
! -------
34+
!
35+
! real(sp), allocatable :: data(:, :)
36+
! call loadtxt("log.txt", data) ! 'data' will be automatically allocated
37+
!
38+
! Where 'log.txt' contains for example::
39+
!
40+
! 1 2 3
41+
! 2 4 6
42+
! 8 9 10
43+
! 11 12 13
44+
! ...
45+
!
46+
integer :: s
47+
integer :: nrow,ncol,i
48+
49+
open(newunit=s, file=filename, status="old")
50+
51+
! determine number of columns
52+
ncol = number_of_columns(s)
53+
54+
! determine number or rows
55+
nrow = number_of_rows_numeric(s)
56+
57+
allocate(d(nrow, ncol))
58+
do i = 1, nrow
59+
read(s, *) d(i, :)
60+
end do
61+
close(s)
2662
end subroutine
2763

2864
subroutine dloadtxt(filename, d)
@@ -50,34 +86,59 @@ subroutine dloadtxt(filename, d)
5086
! 11 12 13
5187
! ...
5288
!
53-
character :: c
54-
integer :: s, ncol, nrow, ios, i
55-
logical :: lastwhite
56-
real(dp) :: r
89+
integer :: s
90+
integer :: nrow,ncol,i
5791

5892
open(newunit=s, file=filename, status="old")
5993

6094
! determine number of columns
61-
ncol = 0
62-
lastwhite = .true.
63-
do
64-
read(s, '(a)', advance='no', iostat=ios) c
65-
if (ios /= 0) exit
66-
if (lastwhite .and. .not. whitechar(c)) ncol = ncol + 1
67-
lastwhite = whitechar(c)
68-
end do
69-
70-
rewind(s)
95+
ncol = number_of_columns(s)
7196

7297
! determine number or rows
73-
nrow = 0
74-
do
75-
read(s, *, iostat=ios) r
76-
if (ios /= 0) exit
77-
nrow = nrow + 1
98+
nrow = number_of_rows_numeric(s)
99+
100+
allocate(d(nrow, ncol))
101+
do i = 1, nrow
102+
read(s, *) d(i, :)
78103
end do
104+
close(s)
105+
end subroutine
106+
107+
subroutine qloadtxt(filename, d)
108+
! Loads a 2D array from a text file.
109+
!
110+
! Arguments
111+
! ---------
112+
!
113+
! Filename to load the array from
114+
character(len=*), intent(in) :: filename
115+
! The array 'd' will be automatically allocated with the correct dimensions
116+
real(qp), allocatable, intent(out) :: d(:,:)
117+
!
118+
! Example
119+
! -------
120+
!
121+
! real(qp), allocatable :: data(:, :)
122+
! call loadtxt("log.txt", data) ! 'data' will be automatically allocated
123+
!
124+
! Where 'log.txt' contains for example::
125+
!
126+
! 1 2 3
127+
! 2 4 6
128+
! 8 9 10
129+
! 11 12 13
130+
! ...
131+
!
132+
integer :: s
133+
integer :: nrow,ncol,i
134+
135+
open(newunit=s, file=filename, status="old")
79136

80-
rewind(s)
137+
! determine number of columns
138+
ncol = number_of_columns(s)
139+
140+
! determine number or rows
141+
nrow = number_of_rows_numeric(s)
81142

82143
allocate(d(nrow, ncol))
83144
do i = 1, nrow
@@ -86,10 +147,28 @@ subroutine dloadtxt(filename, d)
86147
close(s)
87148
end subroutine
88149

150+
89151
subroutine ssavetxt(filename, d)
90-
character(len=*), intent(in) :: filename
91-
real(sp), intent(in) :: d(:,:)
92-
call dsavetxt(filename, real(d,dp))
152+
! Saves a 2D array into a textfile.
153+
!
154+
! Arguments
155+
! ---------
156+
!
157+
character(len=*), intent(in) :: filename ! File to save the array to
158+
real(sp), intent(in) :: d(:,:) ! The 2D array to save
159+
!
160+
! Example
161+
! -------
162+
!
163+
! real(sp) :: data(3, 2)
164+
! call savetxt("log.txt", data)
165+
166+
integer :: s, i
167+
open(newunit=s, file=filename, status="replace")
168+
do i = 1, size(d, 1)
169+
write(s, *) d(i, :)
170+
end do
171+
close(s)
93172
end subroutine
94173

95174
subroutine dsavetxt(filename, d)
@@ -115,6 +194,69 @@ subroutine dsavetxt(filename, d)
115194
close(s)
116195
end subroutine
117196

197+
subroutine qsavetxt(filename, d)
198+
! Saves a 2D array into a textfile.
199+
!
200+
! Arguments
201+
! ---------
202+
!
203+
character(len=*), intent(in) :: filename ! File to save the array to
204+
real(qp), intent(in) :: d(:,:) ! The 2D array to save
205+
!
206+
! Example
207+
! -------
208+
!
209+
! real(dp) :: data(3, 2)
210+
! call savetxt("log.txt", data)
211+
212+
integer :: s, i
213+
open(newunit=s, file=filename, status="replace")
214+
do i = 1, size(d, 1)
215+
write(s, *) d(i, :)
216+
end do
217+
close(s)
218+
end subroutine
219+
220+
221+
integer function number_of_columns(s)
222+
! determine number of columns
223+
integer,intent(in)::s
224+
225+
integer :: ios
226+
character :: c
227+
logical :: lastwhite
228+
229+
rewind(s)
230+
number_of_columns = 0
231+
lastwhite = .true.
232+
do
233+
read(s, '(a)', advance='no', iostat=ios) c
234+
if (ios /= 0) exit
235+
if (lastwhite .and. .not. whitechar(c)) number_of_columns = number_of_columns + 1
236+
lastwhite = whitechar(c)
237+
end do
238+
rewind(s)
239+
240+
end function
241+
242+
integer function number_of_rows_numeric(s)
243+
! determine number or rows
244+
integer,intent(in)::s
245+
integer :: ios
246+
247+
real::r
248+
249+
rewind(s)
250+
number_of_rows_numeric = 0
251+
do
252+
read(s, *, iostat=ios) r
253+
if (ios /= 0) exit
254+
number_of_rows_numeric = number_of_rows_numeric + 1
255+
end do
256+
257+
rewind(s)
258+
259+
end function
118260

119261
logical function whitechar(char) ! white character
120262
! returns .true. if char is space (32) or tab (9), .false. otherwise

src/tests/loadtxt/test_loadtxt.f90

+29-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
program test_loadtxt
2-
use iso_fortran_env, only: dp=>real64
2+
use iso_fortran_env, only: sp=>real32, dp=>real64 ,qp=>real128
33
use stdlib_experimental_io, only: loadtxt
44
implicit none
55

6+
real(sp), allocatable :: s(:, :)
67
real(dp), allocatable :: d(:, :)
8+
real(qp), allocatable :: q(:, :)
9+
10+
call loadtxt("array1.dat", s)
11+
call print_array(s)
12+
713
call loadtxt("array1.dat", d)
814
call print_array(d)
915

@@ -16,15 +22,34 @@ program test_loadtxt
1622
call loadtxt("array4.dat", d)
1723
call print_array(d)
1824

25+
call loadtxt("array4.dat", q)
26+
call print_array(q)
27+
1928
contains
2029

2130
subroutine print_array(a)
22-
real(dp) :: a(:, :)
31+
class(*),intent(in) :: a(:, :)
2332
integer :: i
2433
print *, "Array, shape=(", size(a, 1), ",", size(a, 2), ")"
25-
do i = 1, size(a, 1)
34+
35+
select type(a)
36+
type is(real(sp))
37+
do i = 1, size(a, 1)
2638
print *, a(i, :)
27-
end do
39+
end do
40+
type is(real(dp))
41+
do i = 1, size(a, 1)
42+
print *, a(i, :)
43+
end do
44+
type is(real(qp))
45+
do i = 1, size(a, 1)
46+
print *, a(i, :)
47+
end do
48+
class default
49+
write(*,'(a)')'The proposed type is not supported'
50+
error stop
51+
end select
52+
2853
end subroutine
2954

3055
end program

src/tests/loadtxt/test_savetxt.f90

+18-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
program test_loadtxt
2-
use iso_fortran_env, only: sp=>real32, dp=>real64
2+
use iso_fortran_env, only: sp=>real32, dp=>real64 ,qp=>real128
33
use stdlib_experimental_io, only: loadtxt, savetxt
44
use stdlib_experimental_error, only: assert
55
implicit none
66

77
call test_sp()
88
call test_dp()
9+
call test_qp()
910

1011
contains
1112

@@ -42,4 +43,20 @@ subroutine test_dp()
4243
call assert(all(abs(e-d2) < epsilon(1._dp)))
4344
end subroutine
4445

46+
subroutine test_qp()
47+
real(qp) :: d(3, 2), e(2, 3)
48+
real(qp), allocatable :: d2(:, :)
49+
d = reshape([1, 2, 3, 4, 5, 6], [3, 2])
50+
call savetxt("tmp.dat", d)
51+
call loadtxt("tmp.dat", d2)
52+
call assert(all(shape(d2) == [3, 2]))
53+
call assert(all(abs(d-d2) < epsilon(1._qp)))
54+
55+
e = reshape([1, 2, 3, 4, 5, 6], [2, 3])
56+
call savetxt("tmp.dat", e)
57+
call loadtxt("tmp.dat", d2)
58+
call assert(all(shape(d2) == [2, 3]))
59+
call assert(all(abs(e-d2) < epsilon(1._qp)))
60+
end subroutine
61+
4562
end program

0 commit comments

Comments
 (0)