@@ -29,51 +29,35 @@ module stdlib_str2num
29
29
private
30
30
public :: to_num, to_num_p
31
31
32
- integer, parameter :: ikind = selected_int_kind(2)
33
- integer(kind=ikind), parameter :: digit_0 = ichar('0',kind=ikind)
34
- integer(kind=ikind), parameter :: period = ichar('.',kind=ikind) - digit_0
35
- integer(kind=ikind), parameter :: comma = ichar(',',kind=ikind) - digit_0
36
- integer(kind=ikind), parameter :: minus_sign = ichar('-',kind=ikind) - digit_0
37
- integer(kind=ikind), parameter :: plus_sign = ichar('+',kind=ikind) - digit_0
38
- integer(kind=ikind), parameter :: Inf = ichar('I',kind=ikind)
39
- integer(kind=ikind), parameter :: NaN = ichar('N',kind=ikind)
40
- integer(kind=ikind), parameter :: le = ichar('e',kind=ikind) - digit_0
41
- integer(kind=ikind), parameter :: BE = ichar('E',kind=ikind) - digit_0
42
- integer(kind=ikind), parameter :: ld = ichar('d',kind=ikind) - digit_0
43
- integer(kind=ikind), parameter :: BD = ichar('D',kind=ikind) - digit_0
44
- integer(kind=ikind), parameter :: LF = 10, CR = 13, WS = 32
32
+ integer(int8), parameter :: digit_0 = ichar('0',int8)
33
+ integer(int8), parameter :: period = ichar('.',int8) - digit_0
34
+ integer(int8), parameter :: comma = ichar(',',int8) - digit_0
35
+ integer(int8), parameter :: minus_sign = ichar('-',int8) - digit_0
36
+ integer(int8), parameter :: plus_sign = ichar('+',int8) - digit_0
37
+ integer(int8), parameter :: Inf = ichar('I',int8)
38
+ integer(int8), parameter :: NaN = ichar('N',int8)
39
+ integer(int8), parameter :: le = ichar('e',int8) - digit_0
40
+ integer(int8), parameter :: BE = ichar('E',int8) - digit_0
41
+ integer(int8), parameter :: ld = ichar('d',int8) - digit_0
42
+ integer(int8), parameter :: BD = ichar('D',int8) - digit_0
43
+ integer(int8), parameter :: LF = 10, CR = 13, WS = 32
45
44
46
45
interface to_num
47
- #:for k1, t1 in INT_KINDS_TYPES
46
+ #:for k1, t1 in ( INT_KINDS_TYPES + REAL_KINDS_TYPES)
48
47
module procedure to_${k1}$
49
48
#:endfor
50
- module procedure to_float
51
- module procedure to_double
52
- #:if WITH_QP
53
- module procedure to_quad
54
- #:endif
55
49
end interface
56
50
57
51
interface to_num_p
58
- #:for k1, t1 in INT_KINDS_TYPES
52
+ #:for k1, t1 in ( INT_KINDS_TYPES + REAL_KINDS_TYPES)
59
53
module procedure to_${k1}$_p
60
54
#:endfor
61
- module procedure to_float_p
62
- module procedure to_double_p
63
- #:if WITH_QP
64
- module procedure to_quad_p
65
- #:endif
66
55
end interface
67
56
68
57
interface to_num_base
69
- #:for k1, t1 in INT_KINDS_TYPES
70
- module procedure to_int_ ${k1}$
58
+ #:for k1, t1 in ( INT_KINDS_TYPES + REAL_KINDS_TYPES)
59
+ module procedure to_ ${k1}$_base
71
60
#:endfor
72
- module procedure to_real_sp
73
- module procedure to_real_dp
74
- #:if WITH_QP
75
- module procedure to_real_qp
76
- #:endif
77
61
end interface
78
62
79
63
contains
@@ -82,12 +66,12 @@ module stdlib_str2num
82
66
! String To Number interfaces
83
67
!---------------------------------------------
84
68
85
- #:for k1, t1 in INT_KINDS_TYPES
69
+ #:for k1, t1 in ( INT_KINDS_TYPES + REAL_KINDS_TYPES)
86
70
elemental function to_${k1}$(s,mold) result(v)
87
71
! -- In/out Variables
88
72
character(*), intent(in) :: s !> input string
89
73
${t1}$, intent(in) :: mold !> dummy argument to disambiguate at compile time the generic interface
90
- ${t1}$ :: v !> Output integer 32 value
74
+ ${t1}$ :: v !> Output ${t1}$ value
91
75
! -- Internal Variables
92
76
integer(int8) :: p !> position within the number
93
77
integer(int8) :: stat !> error status
@@ -110,100 +94,14 @@ module stdlib_str2num
110
94
s => s(p:)
111
95
if(present(stat)) stat = err
112
96
end function
113
- #:endfor
114
-
115
- elemental function to_float(s,mold) result(r)
116
- ! -- In/out Variables
117
- character(*), intent(in) :: s !> input string
118
- real(sp), intent(in) :: mold !> dummy argument to disambiguate at compile time the generic interface
119
- real(sp) :: r !> Output real value
120
- ! -- Internal Variables
121
- integer(int8) :: p !> position within the number
122
- integer(int8) :: stat ! error status
123
- !----------------------------------------------
124
- call to_num_base(s,r,p,stat)
125
- end function
126
-
127
- function to_float_p(s,mold,stat) result(r)
128
- ! -- In/out Variables
129
- character(len=:), pointer :: s !> input string
130
- real(sp), intent(in) :: mold !> dummy argument to disambiguate at compile time the generic interface
131
- real(sp) :: r !> Output real value
132
- integer(int8), intent(inout), optional :: stat
133
- ! -- Internal Variables
134
- integer(int8) :: p !> position within the number
135
- integer(int8) :: err
136
- !----------------------------------------------
137
- call to_num_base(s,r,p,err)
138
- p = min( p , len(s) )
139
- s => s(p:)
140
- if(present(stat)) stat = err
141
- end function
142
-
143
- elemental function to_double(s,mold) result(r)
144
- ! -- In/out Variables
145
- character(*), intent(in) :: s !> input string
146
- real(dp), intent(in) :: mold !> dummy argument to disambiguate at compile time the generic interface
147
- real(dp) :: r !> Output real value
148
- ! -- Internal Variables
149
- integer(int8) :: p !> position within the number
150
- integer(int8) :: stat ! error status
151
- !----------------------------------------------
152
- call to_num_base(s,r,p,stat)
153
- end function
154
-
155
- function to_double_p(s,mold,stat) result(r)
156
- ! -- In/out Variables
157
- character(len=:), pointer :: s !> input string
158
- real(dp), intent(in) :: mold !> dummy argument to disambiguate at compile time the generic interface
159
- real(dp) :: r !> Output real value
160
- integer(int8),intent(inout), optional :: stat
161
- ! -- Internal Variables
162
- integer(int8) :: p !> position within the number
163
- integer(int8) :: err
164
- !----------------------------------------------
165
- call to_num_base(s,r,p,err)
166
- p = min( p , len(s) )
167
- s => s(p:)
168
- if(present(stat)) stat = err
169
- end function
170
-
171
- #:if WITH_QP
172
- function to_quad(s,mold) result(r)
173
- ! -- In/out Variables
174
- character(*), intent(in) :: s !> input string
175
- real(qp), intent(in) :: mold !> dummy argument to disambiguate at compile time the generic interface
176
- real(qp) :: r !> Output real value
177
- ! -- Internal Variables
178
- integer(1) :: p !> position within the number
179
- integer(1) :: stat ! error status
180
- !----------------------------------------------
181
- call to_num_base(s,r,p,stat)
182
- end function
183
-
184
- function to_quad_p(s,mold,stat) result(r)
185
- ! -- In/out Variables
186
- character(len=:), pointer :: s !> input string
187
- real(qp), intent(in) :: mold !> dummy argument to disambiguate at compile time the generic interface
188
- real(qp) :: r !> Output real value
189
- integer(int8),intent(inout), optional :: stat
190
- ! -- Internal Variables
191
- integer(int8) :: p !> position within the number
192
- integer(int8) :: err
193
- !----------------------------------------------
194
- call to_num_base(s,r,p,err)
195
- p = min( p , len(s) )
196
- s => s(p:)
197
- if(present(stat)) stat = err
198
- end function
199
- #:endif
200
97
98
+ #:endfor
201
99
!---------------------------------------------
202
100
! String To Number Implementations
203
101
!---------------------------------------------
204
102
205
103
#:for k1, t1 in INT_KINDS_TYPES
206
- elemental subroutine to_int_ ${k1}$(s,v,p,stat)
104
+ elemental subroutine to_ ${k1}$_base (s,v,p,stat)
207
105
!> Return an unsigned 32-bit integer
208
106
! -- In/out Variables
209
107
character(*), intent(in) :: s !> input string
@@ -229,9 +127,10 @@ module stdlib_str2num
229
127
end do
230
128
stat = 0
231
129
end subroutine
130
+
232
131
#:endfor
233
132
234
- elemental subroutine to_real_sp (s,v,p,stat)
133
+ elemental subroutine to_sp_base (s,v,p,stat)
235
134
integer, parameter :: wp = sp
236
135
!> Sequentially unroll the character and get the sub integers composing the whole number, fraction and exponent
237
136
! -- In/out Variables
@@ -241,9 +140,12 @@ module stdlib_str2num
241
140
integer(int8), intent(out) :: stat !> status upon success or failure to read
242
141
243
142
! -- Internal Variables
244
- integer(kind=ikind ), parameter :: nwnb = 39 !> number of whole number factors
245
- integer(kind=ikind ), parameter :: nfnb = 37 !> number of fractional number factors
143
+ integer(int8 ), parameter :: nwnb = 39 !> number of whole number factors
144
+ integer(int8 ), parameter :: nfnb = 37 !> number of fractional number factors
246
145
integer :: e
146
+ ! Notice: We use dp here to obtain exact precision for sp.
147
+ ! Otherwise errors may appear in comparison to formatted read.
148
+ ! See https://github.com/fortran-lang/stdlib/pull/743#issuecomment-1791953430 for more details
247
149
real(dp), parameter :: whole_number_base(nwnb) = [(10._dp**(nwnb-e),e=1,nwnb)]
248
150
real(dp), parameter :: fractional_base(nfnb) = [(10._dp**(-e),e=1,nfnb)]
249
151
real(dp), parameter :: expbase(nwnb+nfnb) = [whole_number_base, fractional_base]
@@ -310,7 +212,7 @@ module stdlib_str2num
310
212
do while( p<=len(s) )
311
213
val = iachar(s(p:p))-digit_0
312
214
if( val >= 0 .and. val <= 9) then
313
- i_exp = i_exp*10_ikind + val ; p = p + 1
215
+ i_exp = i_exp*10_int8 + val ; p = p + 1
314
216
else
315
217
exit
316
218
end if
@@ -325,7 +227,7 @@ module stdlib_str2num
325
227
stat = 0
326
228
end subroutine
327
229
328
- elemental subroutine to_real_dp (s,v,p,stat)
230
+ elemental subroutine to_dp_base (s,v,p,stat)
329
231
integer, parameter :: wp = dp
330
232
!> Sequentially unroll the character and get the sub integers composing the whole number, fraction and exponent
331
233
! -- In/out Variables
@@ -335,8 +237,8 @@ module stdlib_str2num
335
237
integer(int8), intent(out) :: stat !> status upon success or failure to read
336
238
337
239
! -- Internal Variables
338
- integer(kind=ikind ), parameter :: nwnb = 40 !> number of whole number factors
339
- integer(kind=ikind ), parameter :: nfnb = 64 !> number of fractional number factors
240
+ integer(int8 ), parameter :: nwnb = 40 !> number of whole number factors
241
+ integer(int8 ), parameter :: nfnb = 64 !> number of fractional number factors
340
242
integer :: e
341
243
real(wp), parameter :: whole_number_base(nwnb) = [(10._wp**(nwnb-e),e=1,nwnb)]
342
244
real(wp), parameter :: fractional_base(nfnb) = [(10._wp**(-e),e=1,nfnb)]
@@ -404,7 +306,7 @@ module stdlib_str2num
404
306
do while( p<=len(s) )
405
307
val = iachar(s(p:p))-digit_0
406
308
if( val >= 0 .and. val <= 9) then
407
- i_exp = i_exp*10_ikind + val ; p = p + 1
309
+ i_exp = i_exp*10_int8 + val ; p = p + 1
408
310
else
409
311
exit
410
312
end if
@@ -420,7 +322,7 @@ module stdlib_str2num
420
322
end subroutine
421
323
422
324
#:if WITH_QP
423
- subroutine to_real_qp (s,v,p,stat)
325
+ subroutine to_qp_base (s,v,p,stat)
424
326
integer, parameter :: wp = qp
425
327
!> Sequentially unroll the character and get the sub integers composing the whole number, fraction and exponent
426
328
! -- In/out Variables
@@ -430,8 +332,8 @@ module stdlib_str2num
430
332
integer(int8), intent(out) :: stat !> status upon success or failure to read
431
333
432
334
! -- Internal Variables
433
- integer(kind=ikind ), parameter :: nwnb = 50 !> number of whole number factors
434
- integer(kind=ikind ), parameter :: nfnb = 64 !> number of fractional number factors
335
+ integer(int8 ), parameter :: nwnb = 50 !> number of whole number factors
336
+ integer(int8 ), parameter :: nfnb = 64 !> number of fractional number factors
435
337
integer :: e
436
338
real(wp), parameter :: whole_number_base(nwnb) = [(10._wp**(nwnb-e),e=1,nwnb)]
437
339
real(wp), parameter :: fractional_base(nfnb) = [(10._wp**(-e),e=1,nfnb)]
@@ -504,7 +406,7 @@ module stdlib_str2num
504
406
do while( p<=len(s) )
505
407
val = iachar(s(p:p))-digit_0
506
408
if( val >= 0 .and. val <= 9) then
507
- i_exp = i_exp*10_ikind + val ; p = p + 1
409
+ i_exp = i_exp*10_int8 + val ; p = p + 1
508
410
else
509
411
exit
510
412
end if
0 commit comments