web-dev-qa-db-fra.com

Comment initialiser des tableaux bidimensionnels dans Fortran

En C, vous pouvez facilement initialiser un tableau en utilisant la syntaxe des accolades, si je me souviens bien:

int* a = new int[] { 1, 2, 3, 4 };

Comment pouvez-vous faire la même chose dans Fortran pour les tableaux bidimensionnels lorsque vous souhaitez initialiser une matrice avec des valeurs de test spécifiques à des fins mathématiques? (Sans avoir à indexer doublement chaque élément sur des déclarations séparées)

Le tableau est soit défini par

real, dimension(3, 3) :: a

ou

real, dimension(:), allocatable :: a
28
Fludlu McBorry

Vous pouvez le faire en utilisant remodeler et forme intrinsèque. Quelque chose comme:

INTEGER, DIMENSION(3, 3) :: array
array = reshape((/ 1, 2, 3, 4, 5, 6, 7, 8, 9 /), shape(array))

Mais rappelez-vous l'ordre des colonnes majeures. Le tableau sera

1   4   7
2   5   8
3   6   9

après remodelage.

Donc pour obtenir:

1   2   3
4   5   6
7   8   9

vous avez également besoin de transposer intrinsèque:

array = transpose(reshape((/ 1, 2, 3, 4, 5, 6, 7, 8, 9 /), shape(array)))

Pour un exemple plus général (tableau 2D allouable de différentes dimensions), il faut taille intrinsèque:

PROGRAM main

  IMPLICIT NONE

  INTEGER, DIMENSION(:, :), ALLOCATABLE :: array

  ALLOCATE (array(2, 3))

  array = transpose(reshape((/ 1, 2, 3, 4, 5, 6 /),                            &
    (/ size(array, 2), size(array, 1) /)))

  DEALLOCATE (array)

END PROGRAM main
49
Wildcat

Pour les tableaux multidimensionnels (rang> 1), la méthode Fortran pour l'initialisation diffère de la solution C parce qu'en C les tableaux multidimensionnels ne sont que des tableaux de tableaux de etc.

Dans Fortran, chaque rang correspond à un attribut différent du type de données modifié. Mais il n'y a qu'un seul constructeur de tableau, pour les tableaux de rang 1. Pour ces deux raisons, l'initialisation via le constructeur de tableau nécessite la fonction intrisique RESHAPE.

En plus de ce qui a déjà été répondu, il existe un moyen plus direct d'entrer la valeur d'une matrice par ligne plutôt que par colonne: reshape a un argument facultatif ORDER qui peut être utilisé pour modifier l'ordre de remplissage l'élément du tableau multidimensionnel avec les entrées du constructeur du tableau.

Par exemple, dans le cas de l'exemple de la première réponse, on pourrait écrire:

INTEGER, DIMENSION(3, 3) :: array=reshape( (/ 1, 2, 3, &
                                              4, 5, 6, &
                                              7, 8, 9 /), &
                                           shape(array), order=(/2,1/) )

obtenir le remplissage du tableau matriciel exactement dans l'ordre indiqué par les lignes de code.

Le tableau (/2, 1/) force l'index de la colonne (2) pour avoir priorité sur l'index des lignes (1), donnant l'effet souhaité.

18
GiorgioP

L'initialisation d'un tableau peut être effectuée dans l'instruction de déclaration de tableau elle-même, comme illustré ci-dessous:

program test
 real:: x(3) = (/1,2,3/)
 real:: y(3,3) = reshape((/1,2,3,4,5,6,7,8,9/), (/3,3/))
 integer:: i(3,2,2) = reshape((/1,2,3,4,5,6,7,8,9,10,11,12/), (/3,2,2/))

end program test

Cela me surprend que

 real:: y(3,3) = (/(/1,2,3/),(/4,5,6/),(/7,8,9/)/)

est pas accepté par le compilateur (essayé g95, gfortran). Il s'avère que le shape de (/(/1,2,3/),(/4,5,6/),(/7,8,9/)/) est 9 et pas 3 3!

6
Sourav Mukherjee