Array: passaggio a sottoprogrammi

Nel caso di routine senza un'interfaccia esplicita, in F90 le modalità di passaggio degli array a sottoprogrammi sono le stesse del F77, per cui un array usato come argomento in un sottoprogramma può avere le sue dimensioni specificate in varie maniere nel sottoprogramma stesso:
  • costanti, dichiarate da qualche parte come PARAMETER
  • specificate da altri argomenti interi passati al sottoprogramma stesso (adjustable array)
  • nel solo caso dell'ultima dimensione, essa può essere sostituita dal carattere * che sta ad indicare che non è definita a priori (assumed-size array)
L'ultima modalità è da evitare, perché la shape dell'array è in questo caso sconosciuta e il suo uso è quindi molto limitato.

Nel caso una subroutine abbia un'interfaccia (implicita o esplicita che sia), essa può far uso di una modalità più potente di passaggio degli array definita assumed-shape array: in questo caso il sottoprogramma definisce solo il numero di dimensioni dell'array con la notazione array(:,:,...) mentre la shape viene ereditata in maniera automatica dal corrispondente array fornito come argomento della chiamata.

Questa è la maniera consigliata per passare array in quanto non richiede di fare assunzioni sulla shape dell'array (che può essere ricavata con le apposite funzioni intrinseche e non necessita di essere passata) e gli eventuali controlli runtime delle dimensioni degli array funzionano al 100%.

MODULE opvett
CONTAINS

SUBROUTINE op_sum(v, res)
REAL, INTENT(IN) :: v(:,:)
REAL, INTENT(OUT) :: res

PRINT*,'SHAPE:', SHAPE(v)

res = SUM(v)

END SUBROUTINE op_sum

END MODULE opvett

PROGRAM vettori
USE opvett
REAL :: a(12,18), b(18,12), c(12,12)

a=1.
CALL op_sum(a,s)
PRINT*,s

END PROGRAM vettori
F90 permette anche la definizione di array locali ad una subroutine di tipo automatico, si tratta di array locali le cui dimensioni sono specificate a partire da parametri interi ricevuti dalla subroutine stessa o dalla shape di array tipo assumed-shape ricevuti pure come parametri.

La vita degli array di tipo automatico (che non possono per definizione avere l'attributo SAVE) è limitata al tempo di esecuzione del sottoprogramma in cui sono definiti, per cui sono una valida maniera di definire dello "spazio di lavoro" che in F77 doveva essere esplicitamente passato dal programma chiamante.

Nel caso di array di lavoro, l'uso di array automatici è preferibile, per motivi di efficienza, rispetto all'allocazione e deallocazione di variabili ALLOCATABLE ad ogni chiamata; d'altra parte, nel caso di array di grandi dimensioni, lo spazio locale (stack) potrebbe non bastare a contenere tali variabili generando errori runtime di difficile intellegibilità.

MODULE opvett
CONTAINS

SUBROUTINE op_sum(v, res)
REAL, INTENT(IN) :: v(:,:)
REAL, INTENT(OUT) :: res
REAL :: work(SIZE(v,1),SIZE(v,2))

PRINT*,'SHAPE:', SHAPE(v)

work = v
work = LOG(work)
res = SUM(work)

END SUBROUTINE op_sum

END MODULE opvett

PROGRAM vettori
USE opvett
REAL :: a(12,18), b(18,12), c(12,12)

a=1.
CALL op_sum(a,s)
PRINT*,s

END PROGRAM vettori