  PROGRAM Diagonali2
! SCOPO: Calcolo della somma di tutte le diagonali e antidiagonali di una
!   matrice.
! ALGORITMO: si basa sul raddrizzamento in verticale o in orizzontale delle
!   diagonali, mediante scorrimenti differenziati delle righe o delle
!   colonne, e sull'uso delle FUNZIONI VETTORIALI.
! DATI: file di testo che contiene le dimensioni della matrice nel primo(i)
!   record e gli elementi in ordine di riga nei record successivi.
! RISULTATI: le somme sono riportate lungo i bordi della matrice
!--------------------------------------------------------------------------
  IMPLICIT NONE
  INTEGER,ALLOCATABLE:: mat(:,:) ! Matrice
  INTEGER :: n, m                ! e sue dimensioni
  INTEGER :: i, j
  INTEGER,ALLOCATABLE:: shift(:) ! vettore di scorrimento di righe e
                                 ! colonne della matrice
  CHARACTER(LEN=20):: file

  WRITE(*,*) "File di input? "
  READ(*,*) file
  OPEN(1,FILE=file,STATUS='OLD')
  READ(1,*) n, m
  ALLOCATE(mat(1:n+1,0:m+1))! Alloca la matrice bordata a ds, sn e in basso
  ALLOCATE(shift(MAX(n,m))) ! Alloca vettore di scorrimento
  READ(1,*) (mat(i,1:m), i=1,n) ! Carica i dati in mat(1:n,1:m) per righe

!-- Somma le diagonali...
!...che terminano sul lato basso...
!   Verticalizzale con scorrimento differenziato delle righe verso destra
  shift(1:n)=(/ (-(n-i+1), i=1,n) /)! (/ e /) delimitano un "vett.costante"
!   Assegnazione vettoriale: gli array devono essere conformi
!-  Memorizza le somme nel bordo inferiore in linea con le diagonali
  mat(n+1,1:m+1) = SUM(EOSHIFT(        &! Funz. intrinseca di scorrimento
                         mat(1:n,1:m+1)&
                       , shift(1:n)    &! riga i-esima traslata di shift(i)
                       , DIM=2)        &! scorrimento delle righe
                     , DIM=1)           ! somma le colonne
!...e che terminano sul lato destro.
  shift(1:m) = (/ (-(m-j+1), j=1,m) /) ! valori neg., scorr. verso il basso
!   Memorizza le somme nel bordo destro in linea con le diagonali
  mat(1:n,m+1) = SUM(EOSHIFT(mat(1:n,1:m)  &
                           , shift(1:m)    &! la colonna m-esima sta ferma
                           , DIM=1)        &! scorrimento delle colonne
                   , DIM=2)                 ! somma le righe
  WRITE(*,*) "Matrice bordata in basso e a ds. dalle somme delle diagonali"
  WRITE(*,*)
  CALL Scrivi(mat(:,1:m+1))

!-- Somma le antidiagonali...
!... che terminano sul lato basso...
  shift(1:n) = (/ (n-i+1, i=1,n) /)    ! valori positivi, scorr. verso sin.
  mat(n+1,0:m) = SUM(EOSHIFT(mat(1:n,0:m)  &
                             , shift(1:n)  &! la riga n-esima sta ferma
                             , DIM=2)      &
                     , DIM=1)
!... e che terminano sul lato sinistro.     ! Scorr. colonne verso il basso
  shift(1:m) = (/ (-j, j=1,m) /)            ! la prima colonna sta ferma
  mat(1:n,0) = SUM(EOSHIFT(mat(1:n,1:m)    &
                         , shift(1:m)      &
                         , DIM=1)          &
                 , DIM=2)
  WRITE(*,*)
  WRITE(*,*)  &
    "Matrice bordata a sn. e in basso dalle somme delle antidiagonali"
  WRITE(*,*)
  CALL Scrivi(mat(:,0:m))
  STOP

CONTAINS
!--------------------------------------------------------------------
SUBROUTINE Scrivi(mat)
! Scrive la matrice per righe
!--------------------------------------------------------------------
  INTEGER,INTENT(IN) :: mat(:,:)        ! argomento di forma presunta
  INTEGER :: i
  DO i=1,SIZE(mat,1)                    ! fallo per ogni riga
    WRITE(*,*) mat(i,:)                 ! scrivi una riga intera
  END DO
  RETURN
END SUBROUTINE Scrivi

END PROGRAM Diagonali2

