Few years later but just in case this can be of help, here a function that runs 35x faster in O3 and 3x faster in O0 (ifort2023)
module upper_lower
implicit none
contains
pure function to_lower (str) Result (string)
! ==============================
! Changes a string to upper case
! ==============================
Character(*), Intent(In) :: str
Character(LEN(str)) :: string
Integer :: ic, i
Character(26), Parameter :: cap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
Character(26), Parameter :: low = 'abcdefghijklmnopqrstuvwxyz'
! Capitalize each letter if it is lowecase
string = str
do i = 1, LEN_TRIM(str)
ic = INDEX(cap, str(i:i))
if (ic > 0) string(i:i) = low(ic:ic)
end do
end function to_lower
pure function to_lower_2 (str) Result (string)
Character(*), Intent(In) :: str
Character(LEN(str)) :: string
integer, parameter :: wp= 32, la=65, lz= 90
Integer :: c, icar
do c= 1, len(str)
icar= ichar(str(c:c))
if (icar>=la.and.icar<=lz) icar= icar + wp
string(c:c)= char(icar)
end do
end function to_lower_2
pure function to_lower_3(strIn) result(strOut)
! Adapted from original code from Clive page
character(len=*), intent(in) :: strIn
character(len=len(strIn)) :: strOut
integer :: i,j
do i = 1, len(strIn)
j = iachar(strIn(i:i))
if (j>= iachar("A") .and. j<=iachar("Z") ) then
strOut(i:i) = achar(iachar(strIn(i:i))+32)
else
strOut(i:i) = strIn(i:i)
end if
end do
end function to_lower_3
pure function to_upper_2 (str) Result (string)
Character(*), Intent(In) :: str
Character(LEN(str)) :: string
integer, parameter :: wp= 32, BA=97, BZ= 122
Integer :: c, icar
do c= 1, len(str)
icar= ichar(str(c:c))
if (icar>=BA.and.icar<=BZ) icar= icar - wp
string(c:c)= char(icar)
end do
end function to_upper_2
end module
program main
use upper_lower
implicit none
integer :: i
character(len=:),allocatable :: str
real(8) :: t1, t2, t3, time_start, time_finish
str = to_lower_2('Hello, World')
print *, str
str = to_lower_2('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
print *, str
call cpu_time(time_start)
do i = 1,10000000
str = to_lower('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
end do
call cpu_time(time_finish)
t1 = time_finish-time_start
print *, 'Original Method: ', t1
call cpu_time(time_start)
do i = 1,10000000
str = to_lower_2('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
end do
call cpu_time(time_finish)
t2 = time_finish-time_start
print *, 'New Method : ', t2
call cpu_time(time_start)
do i = 1,10000000
str = to_lower_3('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
end do
call cpu_time(time_finish)
t3 = time_finish-time_start
print *, 'Clive: ', t3
print *, 'speedup (t1/t3): ', t1/t3
print *, 'speedup (t2/t3): ', t2/t3
end program main
Output (O3):
hello, world
abcdefghijklmnopqrstuvwxyz
Original Method: 5.48437500000000
New Method : 0.125000000000000
Clive: 7.812500000000000E-002
speedup (t1/t3): 70.2000000000000
speedup (t2/t3): 1.60000000000000
EDIT
Following the remarks in the comments I have updated the comparison, indeed, Clive method is faster in O3, in O0 the second method is about 1.5 times faster