As a little standard exercise, I wrote an integer to roman numerals converter in F03. The result looks already neat enough, for my standards, but I wonder whether it could be made snappier without sacrificing clarity. For folks not familiar with the simple syntax of modern Fortran, I suggest the following quick modern Fortran tutorial.
module mRomanStrings
implicit none
private
character(len=*), parameter :: RM_CHARS = "IVXLCDMvxlcdm_"
integer , parameter :: MAX_ORDER = len(RM_CHARS)/2-1
character(len=4) :: ROMAN_STRING(0:9,0:MAX_ORDER)
logical :: mRomanStringsIsNotInitialized = .TRUE.
public :: IntegerToRoman
contains
function IntegerToRoman(i) result(rm)
integer , intent(in) :: i
character(len=:), allocatable :: rm
integer :: n
if( mRomanStringsIsNotInitialized ) call mRomanSring_init()
rm = " "
do n = min(MAX_ORDER,int(log(dble(i))/log(10.d0)+1.d-10)), 0, -1
rm = trim(rm)//trim(ROMAN_STRING(mod(i/10**n,10),n))
enddo
end function IntegerToRoman
subroutine mRomanSring_init()
character :: a0, a1, a2, a3
integer :: n
do n = 0, MAX_ORDER
a0 = " "
a1 = RM_CHARS(2*n+1:2*n+1)
a2 = RM_CHARS(2*n+2:2*n+2)
a3 = RM_CHARS(2*n+3:2*n+3)
ROMAN_STRING(0:9,n) = [&
a0//a0//a0//a0, a1//a0//a0//a0, a1//a1//a0//a0, a1//a1//a1//a0, a1//a2//a0//a0, &
a2//a0//a0//a0, a2//a1//a0//a0, a2//a1//a1//a0, a2//a1//a1//a1, a1//a3//a0//a0 ]
enddo
mRomanStringsIsNotInitialized = .FALSE.
end subroutine mRomanSring_init
end module mRomanStrings
program ConvertIntegersToRoman
use, intrinsic :: iso_fortran_env
use mRomanStrings
implicit none
integer :: i
do i=1,10000
write(OUTPUT_UNIT,"(i6,x,a)") i, IntegerToRoman(i)
enddo
end program ConvertIntegersToRoman
2 * MAX_ORDER + 3 > size(RM_CHARS)
\$\endgroup\$gfortran -g -Wall -Wextra -Warray-temporaries -Wconversion -fimplicit-none -fbacktrace -ffree-line-length-0 -fcheck=all -ffpe-trap=zero,overflow,underflow -finit-real=nan
You get automatically warned about boundary violations. \$\endgroup\$