2323!> difference rel : 0.3300E-029%
2424
2525module stdlib_str2num
26- use stdlib_kinds, only: sp, dp, qp, int8, int16, int32, int64
26+ use stdlib_kinds, only: sp, dp, xdp, qp, int8, int16, int32, int64
2727 use, intrinsic:: ieee_arithmetic, only: ieee_value, ieee_positive_inf, ieee_quiet_nan
2828 implicit none
2929 private
@@ -44,25 +44,19 @@ module stdlib_str2num
4444
4545 interface to_num
4646 #:for k1, t1 in (INT_KINDS_TYPES + REAL_KINDS_TYPES)
47- #:if k1 != "xdp"
4847 module procedure to_${k1}$
49- #:endif
5048 #:endfor
5149 end interface
5250
5351 interface to_num_p
5452 #:for k1, t1 in (INT_KINDS_TYPES + REAL_KINDS_TYPES)
55- #:if k1 != "xdp"
5653 module procedure to_${k1}$_p
57- #:endif
5854 #:endfor
5955 end interface
6056
6157 interface to_num_base
6258 #:for k1, t1 in (INT_KINDS_TYPES + REAL_KINDS_TYPES)
63- #:if k1 != "xdp"
6459 module procedure to_${k1}$_base
65- #:endif
6660 #:endfor
6761 end interface
6862
@@ -73,7 +67,6 @@ module stdlib_str2num
7367 !---------------------------------------------
7468
7569 #:for k1, t1 in (INT_KINDS_TYPES + REAL_KINDS_TYPES)
76- #:if k1 != "xdp"
7770 elemental function to_${k1}$(s,mold) result(v)
7871 ! -- In/out Variables
7972 character(*), intent(in) :: s !> input string
@@ -102,14 +95,12 @@ module stdlib_str2num
10295 if(present(stat)) stat = err
10396 end function
10497
105- #:endif
10698 #:endfor
10799 !---------------------------------------------
108100 ! String To Number Implementations
109101 !---------------------------------------------
110102
111103 #:for k1, t1 in INT_KINDS_TYPES
112- #:if k1 != "xdp"
113104 elemental subroutine to_${k1}$_base(s,v,p,stat)
114105 !> Return an unsigned 32-bit integer
115106 ! -- In/out Variables
@@ -137,7 +128,6 @@ module stdlib_str2num
137128 stat = 0
138129 end subroutine
139130
140- #:endif
141131 #:endfor
142132
143133 elemental subroutine to_sp_base(s,v,p,stat)
@@ -331,6 +321,111 @@ module stdlib_str2num
331321 stat = 0
332322 end subroutine
333323
324+ #:if WITH_XDP
325+ elemental subroutine to_xdp_base(s,v,p,stat)
326+ integer, parameter :: wp = xdp
327+ !> Sequentially unroll the character and get the sub integers composing the whole number, fraction and exponent
328+ ! -- In/out Variables
329+ character(*), intent(in) :: s !> input string
330+ real(wp), intent(inout) :: v !> Output real value
331+ integer(int8), intent(out) :: p !> last position within the string
332+ integer(int8), intent(out) :: stat !> status upon success or failure to read
333+
334+ ! -- Internal Variables
335+ integer(int8), parameter :: nwnb = 50 !> number of whole number factors
336+ integer(int8), parameter :: nfnb = 64 !> number of fractional number factors
337+ integer :: e
338+ real(wp), parameter :: whole_number_base(nwnb) = [(10._wp**(nwnb-e),e=1,nwnb)]
339+ real(wp), parameter :: fractional_base(nfnb) = [(10._wp**(-e),e=1,nfnb)]
340+ real(wp), parameter :: expbase(nwnb+nfnb) = [whole_number_base, fractional_base]
341+
342+ integer(int8) :: sign, sige !> sign of integer number and exponential
343+ integer, parameter :: maxdpt = 19 !> Maximum depth to read values on int_dp
344+ integer(dp) :: int_dp1, int_dp2 !> long integers to capture whole and fractional part
345+ integer :: i_exp !> integer to capture exponent number
346+ integer :: exp_aux
347+ integer(int8) :: i, pP, pE, val , resp, icount, aux
348+ !----------------------------------------------
349+ stat = 23 !> initialize error status with any number > 0
350+ !----------------------------------------------
351+ ! Find first non white space
352+ p = mvs2nwsp(s)
353+ !----------------------------------------------
354+ ! Verify leading negative
355+ sign = 1
356+ if( iachar(s(p:p)) == minus_sign+digit_0 ) then
357+ sign = -1 ; p = p + 1
358+ end if
359+ if( iachar(s(p:p)) == Inf ) then
360+ v = sign*ieee_value(v, ieee_positive_inf); return
361+ else if( iachar(s(p:p)) == NaN ) then
362+ v = ieee_value(v, ieee_quiet_nan); return
363+ end if
364+ !----------------------------------------------
365+ ! read whole and fractional number using two int64 values
366+ pP = 127
367+ int_dp1 = 0; int_dp2 = 0; icount = 0; aux = 1
368+ do i = p, min(2*maxdpt+p-1,len(s))
369+ val = iachar(s(i:i))-digit_0
370+ if( val >= 0 .and. val <= 9 ) then
371+ icount = icount + 1
372+ if(icount<=maxdpt)then
373+ int_dp1 = int_dp1*10 + val
374+ else if(icount<2*maxdpt)then
375+ int_dp2 = int_dp2*10 + val
376+ end if
377+ else if( val == period ) then
378+ pP = i; aux = 0
379+ else
380+ exit
381+ end if
382+ end do
383+ pE = i ! Fix the exponent position
384+ do while( i<=len(s) )
385+ val = iachar(s(i:i))-digit_0
386+ if( val < 0 .or. val > 9 ) exit
387+ i = i + 1
388+ end do
389+ p = i
390+ resp = pE-min(pP,p) ! If no decimal indicator found it is taken as being in the current p position
391+ if( resp <= 0 ) resp = resp+1
392+ !----------------------------------------------
393+ ! Get exponential
394+ sige = 1
395+ if( p<len(s) ) then
396+ if( any([le,BE,ld,BD]+digit_0==iachar(s(p:p))) ) p = p + 1
397+ if( iachar(s(p:p)) == minus_sign+digit_0 ) then
398+ sige = -1
399+ p = p + 1
400+ else if( iachar(s(p:p)) == plus_sign+digit_0 ) then
401+ p = p + 1
402+ end if
403+ end if
404+
405+ i_exp = 0
406+ do while( p<=len(s) )
407+ val = iachar(s(p:p))-digit_0
408+ if( val >= 0 .and. val <= 9) then
409+ i_exp = i_exp*10_int8 + val ; p = p + 1
410+ else
411+ exit
412+ end if
413+ end do
414+
415+ exp_aux = nwnb-1+resp-sige*i_exp
416+ if( exp_aux>0 .and. exp_aux<=nwnb+nfnb) then
417+ if(icount<=maxdpt)then
418+ v = sign*int_dp1*expbase(exp_aux)
419+ else
420+ v = sign*(int_dp1 + int_dp2*fractional_base(maxdpt-1))*expbase(exp_aux-icount+maxdpt)
421+ end if
422+ else
423+ v = sign*(int_dp1 + int_dp2*fractional_base(maxdpt-1))*10._wp**(sige*i_exp-resp+maxdpt+aux)
424+ end if
425+ stat = 0
426+ end subroutine
427+ #:endif
428+
334429#:if WITH_QP
335430 elemental subroutine to_qp_base(s,v,p,stat)
336431 integer, parameter :: wp = qp
0 commit comments