Skip to content

Commit 22a6dc6

Browse files
jvdp1certik
authored andcommitted
Single and quadruple precisions for load/savetxt
1 parent ae5591f commit 22a6dc6

File tree

3 files changed

+219
-33
lines changed

3 files changed

+219
-33
lines changed

src/stdlib_experimental_io.f90

+172-28
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,65 @@
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

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

2865
subroutine dloadtxt(filename, d)
@@ -50,34 +87,59 @@ subroutine dloadtxt(filename, d)
5087
! 11 12 13
5188
! ...
5289
!
53-
character :: c
54-
integer :: s, ncol, nrow, ios, i
55-
logical :: lastwhite
56-
real(dp) :: r
90+
integer :: s
91+
integer ::nrow,ncol,i
5792

5893
open(newunit=s, file=filename, status="old")
5994

6095
! 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)
96+
ncol=number_of_columns(s)
7197

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

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

82144
allocate(d(nrow, ncol))
83145
do i = 1, nrow
@@ -86,10 +148,28 @@ subroutine dloadtxt(filename, d)
86148
close(s)
87149
end subroutine
88150

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

95175
subroutine dsavetxt(filename, d)
@@ -115,6 +195,70 @@ subroutine dsavetxt(filename, d)
115195
close(s)
116196
end subroutine
117197

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

119263
logical function whitechar(char) ! white character
120264
! 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)