Have you checked in Fortran stdlib
to see what may be available now?
You will know this thread for options relative to C strtod
.
As to “string to int”, you can take inspiration from @lkedward in this thread and trivially get Fortran to give better performance.
C:\Temp>gfortran -O3 p.f90 -o p.exe
C:\Temp>p.exe
C Fortran ratio
times 0.4375 0.1719 0.3929
# mean min max first last maxdiff
10000000 85.3 -500000 499999 -269279 18973 0
Click to see code
program main
use, intrinsic :: iso_c_binding, only: c_char, c_null_char
implicit none
interface
function atoi(in) bind(c)
use, intrinsic :: iso_c_binding
integer(c_int) :: atoi
character(c_char) :: in(*)
end function
end interface
integer :: j,iran
integer, parameter :: nread = 10**7, nt = 3
character(len=10,kind=c_char), allocatable :: digits(:), cdigits(:)
real :: times(nt),dt(nt-1),xran
integer, allocatable :: iran_c(:),iran_f(:)
allocate (digits(nread),cdigits(nread),iran_c(nread),iran_f(nread))
do j=1,nread
call random_number(xran)
iran = 10**6*(xran-0.5) ! random integer
write (digits(j),"(i0)") iran ! write integer to string
cdigits(j) = trim(digits(j)) // c_null_char ! create C string
end do
call cpu_time(times(1))
do j=1,nread ! read integers from C strings using C atoi
iran_c(j) = atoi(cdigits(j))
end do
call cpu_time(times(2))
iran_f = parse_int( digits ) !<-- simple elemental parsing
call cpu_time(times(3))
dt = times(2:nt)-times(1:nt-1)
print "(4a8)","","C","Fortran","ratio"
print "(a8,3f8.4,/)","times",dt,dt(2)/dt(1)
print "(/,*(a8))","#","mean","min","max","first","last","maxdiff"
print "(i8,f8.1,*(i8))",nread,sum(dble(iran_c))/nread,minval(iran_c),maxval(iran_c), &
iran_c(1),iran_c(nread),maxval(abs(iran_c-iran_f))
contains
! Simple variant for base 10 of function by @lkedward toward Julia microbenchmark
elemental function parse_int(s) result(n)
! Argument list
character(len=*), intent(in) :: s
! Function result
integer :: n
! Local variables
integer :: i, d, sign
character :: c
n = 0
sign = 1
loop_digits: do i = 1, len_trim(s)
c = s(i:i)
d = 0
select case ( ichar(c) )
case ( ichar('0'):ichar('9') )
d = ichar(c) - ichar('0')
case ( ichar('-') )
sign = -1
cycle loop_digits
case ( ichar(' ') )
cycle loop_digits
case default
error stop "parse error"
end select
n = n*10 + d
end do loop_digits
n = sign*n
end function
end program main