11#:include "common.fypp"
22!> The `stdlib_str2num` module provides procedures and interfaces for conversion
33!> of characters to numerical types. Currently supported: `integer` and `real`.
4- !! ([Specification](../page/specs/stdlib_str2num.html)
4+ !> ([Specification](../page/specs/stdlib_str2num.html) )
55!>
66!> This code was modified from https://github.com/jalvesz/Fortran-String-to-Num by Alves Jose
77!> And was possible thanks to all the discussions in this thread https://fortran-lang.discourse.group/t/faster-string-to-double/
88!>
99!> Known precisions limits of current proposal :
1010!> Conversion to double precision is exact up to epsilon(0.0_dp)
1111!> example:
12+ !>
1213!> input : 123456.78901234567890123456789012345678901234567890+2
14+ !>
1315!> formatted read : 12345678.90123457
16+ !>
1417!> to_num : 12345678.90123457
18+ !>
1519!> difference abs : 0.1862645149230957E-08
20+ !>
1621!> difference rel : 0.1508742584455759E-13%
1722!>
1823!> Conversion to quadruple precision can deviate at about 200*epsilon(0.0_qp)
1924!> example:
25+ !>
2026!> input : 0.140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125E-443
27+ !>
2128!> formatted read : 0.140129846432481707092372958328991608E-443
29+ !>
2230!> to_num : 0.140129846432481707092372958328996233E-443
31+ !>
2332!> difference abs : 0.4625E-475
33+ !>
2434!> difference rel : 0.3300E-029%
2535
2636module stdlib_str2num
@@ -78,24 +88,24 @@ module stdlib_str2num
7888 #:for k1, t1 in (INT_KINDS_TYPES + REAL_KINDS_TYPES)
7989 elemental function to_${k1}$(s,mold) result(v)
8090 ! -- In/out Variables
81- character(*), intent(in) :: s !> input string
82- ${t1}$, intent(in) :: mold !> dummy argument to disambiguate at compile time the generic interface
83- ${t1}$ :: v !> Output ${t1}$ value
91+ character(*), intent(in) :: s !! input string
92+ ${t1}$, intent(in) :: mold !! dummy argument to disambiguate at compile time the generic interface
93+ ${t1}$ :: v !! Output ${t1}$ value
8494 ! -- Internal Variables
85- integer(int8) :: p !> position within the number
86- integer(int8) :: stat !> error status
95+ integer(int8) :: p !! position within the number
96+ integer(int8) :: stat !! error status
8797 !----------------------------------------------
8898 call to_num_base(s,v,p,stat)
8999 end function
90100
91101 function to_${k1}$_from_stream(s,mold,stat) result(v)
92102 ! -- In/out Variables
93- character(len=:), pointer :: s !> input string
94- ${t1}$, intent(in) :: mold !> dummy argument to disambiguate at compile time the generic interface
95- ${t1}$ :: v !> Output ${t1}$ value
103+ character(len=:), pointer :: s !! input string
104+ ${t1}$, intent(in) :: mold !! dummy argument to disambiguate at compile time the generic interface
105+ ${t1}$ :: v !! Output ${t1}$ value
96106 integer(int8),intent(inout), optional :: stat
97107 ! -- Internal Variables
98- integer(int8) :: p !> position within the number
108+ integer(int8) :: p !! position within the number
99109 integer(int8) :: err
100110 !----------------------------------------------
101111 call to_num_base(s,v,p,err)
@@ -111,16 +121,16 @@ module stdlib_str2num
111121
112122 #:for k1, t1 in INT_KINDS_TYPES
113123 elemental subroutine to_${k1}$_base(s,v,p,stat)
114- !> Return an ${k1}$ integer
124+ !! Return an ${k1}$ integer
115125 ! -- In/out Variables
116- character(*), intent(in) :: s !> input string
117- ${t1}$, intent(out) :: v !> Output real value
118- integer(int8), intent(out) :: p !> position within the number
119- integer(int8), intent(out) :: stat !> status upon succes or failure to read
126+ character(*), intent(in) :: s !! input string
127+ ${t1}$, intent(out) :: v !! Output real value
128+ integer(int8), intent(out) :: p !! position within the number
129+ integer(int8), intent(out) :: stat !! status upon succes or failure to read
120130 ! -- Internal Variables
121131 integer(int8) :: val
122132 !----------------------------------------------
123- stat = 23 !> initialize error status with any number > 0
133+ stat = 23 !! initialize error status with any number > 0
124134 !----------------------------------------------
125135 ! Find first non white space
126136 p = shift_to_nonwhitespace(s)
@@ -142,16 +152,16 @@ module stdlib_str2num
142152
143153 elemental subroutine to_sp_base(s,v,p,stat)
144154 integer, parameter :: wp = sp
145- !> Sequentially unroll the character and get the sub integers composing the whole number, fraction and exponent
155+ !! Sequentially unroll the character and get the sub integers composing the whole number, fraction and exponent
146156 ! -- In/out Variables
147- character(*), intent(in) :: s !> input string
148- real(wp), intent(inout) :: v !> Output real value
149- integer(int8), intent(out) :: p !> last position within the string
150- integer(int8), intent(out) :: stat !> status upon success or failure to read
157+ character(*), intent(in) :: s !! input string
158+ real(wp), intent(inout) :: v !! Output real value
159+ integer(int8), intent(out) :: p !! last position within the string
160+ integer(int8), intent(out) :: stat !! status upon success or failure to read
151161
152162 ! -- Internal Variables
153- integer(int8), parameter :: nwnb = 39 !> number of whole number factors
154- integer(int8), parameter :: nfnb = 37 !> number of fractional number factors
163+ integer(int8), parameter :: nwnb = 39 !! number of whole number factors
164+ integer(int8), parameter :: nfnb = 37 !! number of fractional number factors
155165 integer :: e
156166 ! Notice: We use dp here to obtain exact precision for sp.
157167 ! Otherwise errors may appear in comparison to formatted read.
@@ -160,14 +170,14 @@ module stdlib_str2num
160170 real(dp), parameter :: fractional_base(nfnb) = [(10._dp**(-e),e=1,nfnb)]
161171 real(dp), parameter :: expbase(nwnb+nfnb) = [whole_number_base, fractional_base]
162172
163- integer(int8) :: sign, sige !> sign of integer number and exponential
164- integer, parameter :: maxdpt = 11 !> Maximum depth to read values on int_wp
165- integer(dp) :: int_wp !> long integer to capture fractional part
166- integer :: i_exp !> integer to capture whole number part
173+ integer(int8) :: sign, sige !! sign of integer number and exponential
174+ integer, parameter :: maxdpt = 11 !! Maximum depth to read values on int_wp
175+ integer(dp) :: int_wp !! long integer to capture fractional part
176+ integer :: i_exp !! integer to capture whole number part
167177 integer :: exp_aux
168178 integer(int8) :: i, pP, pE, val , resp
169179 !----------------------------------------------
170- stat = 23 !> initialize error status with any number > 0
180+ stat = 23 !! initialize error status with any number > 0
171181 !----------------------------------------------
172182 ! Find first non white space
173183 p = shift_to_nonwhitespace(s)
@@ -243,29 +253,29 @@ module stdlib_str2num
243253
244254 elemental subroutine to_dp_base(s,v,p,stat)
245255 integer, parameter :: wp = dp
246- !> Sequentially unroll the character and get the sub integers composing the whole number, fraction and exponent
256+ !! Sequentially unroll the character and get the sub integers composing the whole number, fraction and exponent
247257 ! -- In/out Variables
248- character(*), intent(in) :: s !> input string
249- real(wp), intent(inout) :: v !> Output real value
250- integer(int8), intent(out) :: p !> last position within the string
251- integer(int8), intent(out) :: stat !> status upon success or failure to read
258+ character(*), intent(in) :: s !! input string
259+ real(wp), intent(inout) :: v !! Output real value
260+ integer(int8), intent(out) :: p !! last position within the string
261+ integer(int8), intent(out) :: stat !! status upon success or failure to read
252262
253263 ! -- Internal Variables
254- integer(int8), parameter :: nwnb = 40 !> number of whole number factors
255- integer(int8), parameter :: nfnb = 64 !> number of fractional number factors
264+ integer(int8), parameter :: nwnb = 40 !! number of whole number factors
265+ integer(int8), parameter :: nfnb = 64 !! number of fractional number factors
256266 integer :: e
257267 real(wp), parameter :: whole_number_base(nwnb) = [(10._wp**(nwnb-e),e=1,nwnb)]
258268 real(wp), parameter :: fractional_base(nfnb) = [(10._wp**(-e),e=1,nfnb)]
259269 real(wp), parameter :: expbase(nwnb+nfnb) = [whole_number_base, fractional_base]
260270
261- integer(int8) :: sign, sige !> sign of integer number and exponential
262- integer, parameter :: maxdpt = 19 !> Maximum depth to read values on int_wp
263- integer(wp) :: int_wp !> long integer to capture fractional part
264- integer :: i_exp !> integer to capture whole number part
271+ integer(int8) :: sign, sige !! sign of integer number and exponential
272+ integer, parameter :: maxdpt = 19 !! Maximum depth to read values on int_wp
273+ integer(wp) :: int_wp !! long integer to capture fractional part
274+ integer :: i_exp !! integer to capture whole number part
265275 integer :: exp_aux
266276 integer(int8) :: i, pP, pE, val , resp
267277 !----------------------------------------------
268- stat = 23 !> initialize error status with any number > 0
278+ stat = 23 !! initialize error status with any number > 0
269279 !----------------------------------------------
270280 ! Find first non white space
271281 p = shift_to_nonwhitespace(s)
@@ -342,29 +352,29 @@ module stdlib_str2num
342352#:if WITH_XDP
343353 elemental subroutine to_xdp_base(s,v,p,stat)
344354 integer, parameter :: wp = xdp
345- !> Sequentially unroll the character and get the sub integers composing the whole number, fraction and exponent
355+ !! Sequentially unroll the character and get the sub integers composing the whole number, fraction and exponent
346356 ! -- In/out Variables
347- character(*), intent(in) :: s !> input string
348- real(wp), intent(inout) :: v !> Output real value
349- integer(int8), intent(out) :: p !> last position within the string
350- integer(int8), intent(out) :: stat !> status upon success or failure to read
357+ character(*), intent(in) :: s !! input string
358+ real(wp), intent(inout) :: v !! Output real value
359+ integer(int8), intent(out) :: p !! last position within the string
360+ integer(int8), intent(out) :: stat !! status upon success or failure to read
351361
352362 ! -- Internal Variables
353- integer(int8), parameter :: nwnb = 50 !> number of whole number factors
354- integer(int8), parameter :: nfnb = 64 !> number of fractional number factors
363+ integer(int8), parameter :: nwnb = 50 !! number of whole number factors
364+ integer(int8), parameter :: nfnb = 64 !! number of fractional number factors
355365 integer :: e
356366 real(wp), parameter :: whole_number_base(nwnb) = [(10._wp**(nwnb-e),e=1,nwnb)]
357367 real(wp), parameter :: fractional_base(nfnb) = [(10._wp**(-e),e=1,nfnb)]
358368 real(wp), parameter :: expbase(nwnb+nfnb) = [whole_number_base, fractional_base]
359369
360- integer(int8) :: sign, sige !> sign of integer number and exponential
361- integer, parameter :: maxdpt = 19 !> Maximum depth to read values on int_dp
362- integer(dp) :: int_dp1, int_dp2 !> long integers to capture whole and fractional part
363- integer :: i_exp !> integer to capture exponent number
370+ integer(int8) :: sign, sige !! sign of integer number and exponential
371+ integer, parameter :: maxdpt = 19 !! Maximum depth to read values on int_dp
372+ integer(dp) :: int_dp1, int_dp2 !! long integers to capture whole and fractional part
373+ integer :: i_exp !! integer to capture exponent number
364374 integer :: exp_aux
365375 integer(int8) :: i, pP, pE, val , resp, icount, aux
366376 !----------------------------------------------
367- stat = 23 !> initialize error status with any number > 0
377+ stat = 23 !! initialize error status with any number > 0
368378 !----------------------------------------------
369379 ! Find first non white space
370380 p = shift_to_nonwhitespace(s)
@@ -455,29 +465,29 @@ module stdlib_str2num
455465#:if WITH_QP
456466 elemental subroutine to_qp_base(s,v,p,stat)
457467 integer, parameter :: wp = qp
458- !> Sequentially unroll the character and get the sub integers composing the whole number, fraction and exponent
468+ !! Sequentially unroll the character and get the sub integers composing the whole number, fraction and exponent
459469 ! -- In/out Variables
460- character(*), intent(in) :: s !> input string
461- real(wp), intent(inout) :: v !> Output real value
462- integer(int8), intent(out) :: p !> last position within the string
463- integer(int8), intent(out) :: stat !> status upon success or failure to read
470+ character(*), intent(in) :: s !! input string
471+ real(wp), intent(inout) :: v !! Output real value
472+ integer(int8), intent(out) :: p !! last position within the string
473+ integer(int8), intent(out) :: stat !! status upon success or failure to read
464474
465475 ! -- Internal Variables
466- integer(int8), parameter :: nwnb = 50 !> number of whole number factors
467- integer(int8), parameter :: nfnb = 64 !> number of fractional number factors
476+ integer(int8), parameter :: nwnb = 50 !! number of whole number factors
477+ integer(int8), parameter :: nfnb = 64 !! number of fractional number factors
468478 integer :: e
469479 real(wp), parameter :: whole_number_base(nwnb) = [(10._wp**(nwnb-e),e=1,nwnb)]
470480 real(wp), parameter :: fractional_base(nfnb) = [(10._wp**(-e),e=1,nfnb)]
471481 real(wp), parameter :: expbase(nwnb+nfnb) = [whole_number_base, fractional_base]
472482
473- integer(int8) :: sign, sige !> sign of integer number and exponential
474- integer, parameter :: maxdpt = 19 !> Maximum depth to read values on int_dp
475- integer(dp) :: int_dp1, int_dp2 !> long integers to capture whole and fractional part
476- integer :: i_exp !> integer to capture exponent number
483+ integer(int8) :: sign, sige !! sign of integer number and exponential
484+ integer, parameter :: maxdpt = 19 !! Maximum depth to read values on int_dp
485+ integer(dp) :: int_dp1, int_dp2 !! long integers to capture whole and fractional part
486+ integer :: i_exp !! integer to capture exponent number
477487 integer :: exp_aux
478488 integer(int8) :: i, pP, pE, val , resp, icount, aux
479489 !----------------------------------------------
480- stat = 23 !> initialize error status with any number > 0
490+ stat = 23 !! initialize error status with any number > 0
481491 !----------------------------------------------
482492 ! Find first non white space
483493 p = shift_to_nonwhitespace(s)
@@ -570,9 +580,9 @@ module stdlib_str2num
570580 !---------------------------------------------
571581
572582 elemental function shift_to_nonwhitespace(s) result(p)
573- !> move string to position of the next non white space character
574- character(*),intent(in) :: s !> character chain
575- integer(int8) :: p !> position
583+ !! move string to position of the next non white space character
584+ character(*),intent(in) :: s !! character chain
585+ integer(int8) :: p !! position
576586 !----------------------------------------------
577587 p = 1
578588 do while( p<len(s) .and. (iachar(s(p:p))==WS .or. iachar(s(p:p))==LF .or. iachar(s(p:p))==CR) )
@@ -581,9 +591,9 @@ module stdlib_str2num
581591 end function
582592
583593 elemental function shift_to_whitespace(s) result(p)
584- !> move string to position of the next white space character
585- character(*),intent(in) :: s !> character chain
586- integer(int8) :: p !> position
594+ !! move string to position of the next white space character
595+ character(*),intent(in) :: s !! character chain
596+ integer(int8) :: p !! position
587597 !----------------------------------------------
588598 p = 1
589599 do while( p<len(s) .and. .not.(iachar(s(p:p))==WS .or. iachar(s(p:p))==LF .or. iachar(s(p:p))==CR) )
0 commit comments