Continua la telenovela delle cose nuove del Fortran. Siccome ero rimasto fermo al 77 le novità sono parecchie ma prima o poi si arriverà vedere la luce alla fine del tunnel.

Una cosa che diverse implementazioni avevano introdotto, ognuna in modo diverso, era di sopprimere l’a capo finale del print / write. Ora è standardizzato.
program nonl !no advance implicit none integer i write(6, fmt='(A)') 'test di ADVANCE' write(6, fmt='(A)', ADVANCE='NO') 'dammi un numero: ' read(5, *) i print *, i end

E seguendo altri linguaggi c’è una funzione per l’a capo, come l’endl del C++.
program nl ! new_line implicit none character(10) :: c = 'ciao' integer :: i i = ichar(new_line(c)) print '(A, i3, 1x, A, A)', 'ecco vale ', i, new_line(c), 'visto?' print * print '(A, /, A)', 'la versione classica', 'è questa' end

Le procedure (subroutines e funzioni) possono avere parametri opzionali, con l’avvertenza di inserire un’interfaccia (quasi come il C).
program optarg
implicit none
integer :: uno, due, tre, quattro
interface
subroutine p_show(i1, i2, i3, i4)
integer :: i1, i2
integer, optional :: i3, i4
end subroutine
end interface
call p_show(1, 2, 3, 4)
call p_show(1, 2)
call p_show(1, 2, 3)
call p_show(1, 2, i4=8)
end
subroutine p_show(a, b, c, d)
implicit none
integer :: a, b
integer, optional :: c, d
logical :: lc, ld
lc = present(c)
ld = present(d)
print *, a, b, lc, ld
if (lc) print *, c
if (ld) print *, d
end

Siccome l’interfaccia dev’essere spesso ripetuta torna utile e raccomandatissima l’istruzione include.
program incl ! x include
implicit none
include 'my_sum.inc'
print *, my_sum(1, 2, 3)
print *, mY_sum(4, 5)
call my_sub
end
integer function my_sum(i1, i2, i3) result (s)
integer :: i1, i2
integer, optional :: i3
s = i1 + i2
if (present(i3)) s = s + i3
end function
subroutine my_sub
implicit none
include 'my_sum.inc'
print *, new_line(' '), 'in my_sub'
print *, my_sum(6, 7)
end

e questo è il file my_sum.inc da includere in ogni procedura che chiama la funzione.
interface
integer function my_sum(i1, i2, i3) result (s)
integer :: i1, i2
integer, optional :: i3
end function
end interface
Fin da sempre il modulo di due numeri si faceva con mod; adesso c’è anche modulo. Sono equivalenti se i due numeri sono positivi, altrimenti no, devo ancora approfondire, per adesso prevedo casini (non nel senso di Pierferdinando, quello è peggio).
program modx ! diffferenza tra mod e modulo -> 180 print *, mod(10, 3), modulo(10, 3) print *, mod(-10, 3), modulo(-10, 3) print *, mod(10, -3), modulo(10, -3) print *, mod(-10, -3), modulo(-10, -3) end

Esistono interi davvero grandi (9 * 10^18).
program kinds
implicit none
integer(1) i1
integer(2) i2
integer(4) i4
integer(8) i8
print *, kind(i1), kind(i2), kind(i4), kind(i8)
print *, range(i1), range(i2), range(i4), range(i8)
print *, huge(i1), huge(i2), huge(i4), huge(i8)
print *, int(log10(real(huge(i1)))), int(log10(real(huge(i2)))), &
& int(log10(real(huge(i4)))), int(log10(real(huge(i8))))
end

Sono predefinite parecchie costanti, eccone alcune del modulo ISO_FORTRAN_ENV.
program const !costanti in iso_fortran_env use iso_fortran_env implicit none print *, ATOMIC_INT_KIND, ATOMIC_LOGICAL_KIND, CHARACTER_KINDS print *, CHARACTER_STORAGE_SIZE, FILE_STORAGE_SIZE print *, INT8, INT16, INT32, INT64 print *, INTEGER_KINDS print *, LOGICAL_KINDS print *, REAL32, REAL64, REAL128 print *, REAL_KINDS end

Per i real verifico il valore (assoluto) massimo e quello più prossimo a zero.
program reals use iso_fortran_env implicit none integer :: realkinds(4), i real(4) :: r4 real(8) :: r8 real(10) :: r10 real(16) :: r16 realkinds = REAL_KINDS print '(4(1x, i3))', realkinds print *, 4, tiny(r4) print *, 8, tiny(r8) print *, 10, tiny(r10) print *, 16, tiny(r16) print * print *, 4, huge(r4) print *, 8, huge(r8) print *, 10, huge(r10) print *, 16, huge(r16) end

OK, credo che per oggi possa bastare
