23
23
!> difference rel : 0.3300E-029%
24
24
25
25
module 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
27
27
use, intrinsic:: ieee_arithmetic, only: ieee_value, ieee_positive_inf, ieee_quiet_nan
28
28
implicit none
29
29
private
@@ -44,25 +44,19 @@ module stdlib_str2num
44
44
45
45
interface to_num
46
46
#:for k1, t1 in (INT_KINDS_TYPES + REAL_KINDS_TYPES)
47
- #:if k1 != "xdp"
48
47
module procedure to_${k1}$
49
- #:endif
50
48
#:endfor
51
49
end interface
52
50
53
51
interface to_num_p
54
52
#:for k1, t1 in (INT_KINDS_TYPES + REAL_KINDS_TYPES)
55
- #:if k1 != "xdp"
56
53
module procedure to_${k1}$_p
57
- #:endif
58
54
#:endfor
59
55
end interface
60
56
61
57
interface to_num_base
62
58
#:for k1, t1 in (INT_KINDS_TYPES + REAL_KINDS_TYPES)
63
- #:if k1 != "xdp"
64
59
module procedure to_${k1}$_base
65
- #:endif
66
60
#:endfor
67
61
end interface
68
62
@@ -73,7 +67,6 @@ module stdlib_str2num
73
67
!---------------------------------------------
74
68
75
69
#:for k1, t1 in (INT_KINDS_TYPES + REAL_KINDS_TYPES)
76
- #:if k1 != "xdp"
77
70
elemental function to_${k1}$(s,mold) result(v)
78
71
! -- In/out Variables
79
72
character(*), intent(in) :: s !> input string
@@ -102,14 +95,12 @@ module stdlib_str2num
102
95
if(present(stat)) stat = err
103
96
end function
104
97
105
- #:endif
106
98
#:endfor
107
99
!---------------------------------------------
108
100
! String To Number Implementations
109
101
!---------------------------------------------
110
102
111
103
#:for k1, t1 in INT_KINDS_TYPES
112
- #:if k1 != "xdp"
113
104
elemental subroutine to_${k1}$_base(s,v,p,stat)
114
105
!> Return an unsigned 32-bit integer
115
106
! -- In/out Variables
@@ -137,7 +128,6 @@ module stdlib_str2num
137
128
stat = 0
138
129
end subroutine
139
130
140
- #:endif
141
131
#:endfor
142
132
143
133
elemental subroutine to_sp_base(s,v,p,stat)
@@ -331,6 +321,111 @@ module stdlib_str2num
331
321
stat = 0
332
322
end subroutine
333
323
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
+
334
429
#:if WITH_QP
335
430
elemental subroutine to_qp_base(s,v,p,stat)
336
431
integer, parameter :: wp = qp
0 commit comments