Sök…


Grundläggande notation

Vilken typ som helst kan deklareras som en matris med antingen dimensionattributet eller genom att bara ange dimension (er) för matrisen:

! One dimensional array with 4 elements
integer, dimension(4) :: foo

! Two dimensional array with 4 rows and 2 columns
real, dimension(4, 2) :: bar

! Three dimensional array
type(mytype), dimension(6, 7, 8) :: myarray

! Same as above without using the dimension keyword
integer :: foo2(4)
real :: bar2(4, 2)
type(mytype) :: myarray2(6, 7, 8)

Det senare sättet att deklarera multidimensionell matris, tillåter deklarering av olika typer av olika rang / dimensioner i en rad, enligt följande

real :: pencil(5), plate(3,-2:4), cuboid(0:3,-10:5,6)

Den högsta tillåtna rankningen (antalet dimensioner) är 15 i Fortran 2008-standarden och var 7 tidigare.

Fortran lagrar matriser i kolumn- huvudordning. Det vill säga elementen i bar lagras i minnet enligt följande:

bar(1, 1), bar(2, 1), bar(3, 1), bar(4, 1), bar(1, 2), bar(2, 2), ...

I Fortran startar matrisnumreringen vid 1 som standard, i motsats till C som börjar vid 0 . I Fortran kan du faktiskt ange de övre och nedre gränserna för varje dimension uttryckligen:

integer, dimension(7:12, -3:-1) :: geese

Detta förklarar en matrisform (6, 3) , vars första element är geese(7, -3) .

Nedre och övre gränser längs de 2 (eller fler) dimensionerna kan nås av de inneboende funktionerna ubound och lbound . I lbound(geese,2) verket skulle lbound(geese,2) återvända -3 , medan ubound(geese,1) skulle återvända 12 .

Storleken av en array kan nås genom inneboende funktion size . Till exempel ger size(geese, dim = 1) storleken på den första dimensionen som är 6.

Tilldelbara matriser

Matriser kan ha det allokerbara attributet:

! One dimensional allocatable array
integer, dimension(:), allocatable :: foo
! Two dimensional allocatable array
real, dimension(:,:), allocatable :: bar

Detta deklarerar variabeln men tilldelar inte utrymme för den.

! We can specify the bounds as usual
allocate(foo(3:5))

! It is an error to allocate an array twice
! so check it has not been allocated first
if (.not. allocated(foo)) then
  allocate(bar(10, 2))
end if

När inte längre behövs en variabel, kan det avallokeras:

deallocate(foo)

Om du av någon anledning en allocate uttalande misslyckas, kommer programmet att sluta. Detta kan förhindras om status kontrolleras via stat nyckelordet:

real, dimension(:), allocatable :: geese
integer :: status

allocate(geese(17), stat=status)
if (stat /= 0) then
  print*, "Something went wrong trying to allocate 'geese'"
  stop 1
end if

deallocate uttalandet har också nyckelord för stat :

deallocate (geese, stat=status)

status är en heltalvariabel vars värde är 0 om allokeringen eller omfördelningen var framgångsrik.

Arraykonstruktörer

Ett rank-1-arrayvärde kan skapas med hjälp av en array-konstruktör med syntaxen

(/ ... /)
[ ... ]

Formen [...] introducerades i Fortran 2003 och betraktas generellt som tydligare att läsa, särskilt i komplexa uttryck. Denna form används exklusivt i detta exempel.

Värdena som finns i en matriskonstruktör kan vara skalvärden, matrisvärden eller implicit-loopar.

Typen och typparametrarna för den konstruerade arrayen matchar värdena i arraykonstruktören

[1, 2, 3]      ! A rank-1 length-3 array of default integer type
[1., 2., 3.]   ! A rank-1 length-3 array of default real type
["A", "B"]     ! A rank-1 length-2 array of default character type

integer, parameter :: A = [2, 4]
[1, A, 3]      ! A rank-1 length-4 array of default integer type, with A's elements

integer i
[1, (i, i=2, 5), 6]  ! A rank-1 length-6 array of default integer type with an implied-do

I formulärerna ovan måste alla angivna värden vara av samma typ och typparameter. Blandningstyper eller typparametrar är inte tillåtet. Följande exempel är inte giltiga

[1, 2.]      ! INVALID: Mixing integer and default real
[1e0, 2d0]   ! INVALID: Mixing default real and double precision
[1., 2._dp]  ! INVALID: Allowed only if kind `dp` corresponds to default real
["Hello", "Frederick"]  ! INVALID: Different length parameters

För att konstruera en matris med olika typer ska en typspecifikation för matrisen ges

[integer :: 1, 2., 3d0]    ! A default integer array
[real(dp) :: 1, 2, 3._sp]  ! A real(dp) array
[character(len=9) :: "Hello", "Frederick"]  ! A length-2 array of length-9 characters

Den senare formen för karaktärsuppsättningar är särskilt bekväm att undvika rymdstoppning, såsom alternativet

["Hello    ", "Frederick"]  ! A length-2 array of length-9 characters

Storleken på en matris med namnet konstant kan antydas av den arraykonstruktör som används för att ställa in dess värde

integer, parameter :: ids(*) = [1, 2, 3, 4]

och för längdparametrerade typer kan längdparametern antas

character(len=*), parameter :: names(*) = [character(3) :: "Me", "You", "Her"]

Typspecifikationen krävs också vid konstruktion av noll-längd arrayer. Från

[ ] ! Not a valid array constructor

parametrarna för typ och typ kan inte bestämmas utifrån den icke-existerande värdesättningen. Så här skapar du en heltalsfärg med noll längd:

[integer :: ]

Arraykonstruktörer konstruerar endast rang-1-matriser. Ibland, såsom att ställa in värdet på en namngiven konstant, krävs också högre rangordning i ett uttryck. Matriser med högre rang kan tas från resultatet av reshape med en konstruerad rang-1-array

integer, parameter :: multi_rank_ids(2,2) = RESHAPE([1,2,3,4], shape=[2,2])

I en arraykonstruktör är värdena på matrisen i elementordning med alla arrayer i värdelistan som om de enskilda elemeterna gavs sig i matriselementordning. Således, det tidigare exemplet

integer, parameter :: A = [2, 4]
[1, A, 3]      ! A rank-1 length-4 array of default integer type, with A's elements

är ekvivalent med

[1, 2, 4, 3]   ! With the array written out in array element order

Generellt kan värdena i konstruktören vara godtyckliga uttryck, inklusive kapslade arraykonstruktörer. För att en sådan matriskonstruktör uppfyller vissa villkor, såsom att vara ett konstant eller specifikationsuttryck, gäller begränsningar för beståndsdelar.


Även om det inte är en arraykonstruktör, kan vissa matrisvärden också bekvämt skapas med användning av den inre funktionen spread . Till exempel

[(0, i=1,10)]  ! An array with 10 default integers each of value 0

är också resultatet av funktionsreferensen

SPREAD(0, 1, 10)

Specifikationer för array: rang och form

dimension på ett objekt anger att det objektet är en matris. I Fortran 2008 finns det fem matriser: 1

  • uttrycklig form
  • antagen form
  • antagen storlek
  • uppskjuten form
  • underförstådd form

Ta de tre rank-1 matriserna 2

integer a, b, c
dimension(5) a    ! Explicit shape (default lower bound 1), extent 5
dimension(:) b    ! Assumed or deferred shape
dimension(*) c    ! Assumed size or implied shape array

Med dessa kan man se att ytterligare sammanhang krävs för att fullständigt bestämma arrayens art.

Explicit form

En tydlig formuppsättning är alltid formen på dess deklaration. Om inte matrisen förklaras som lokal för ett underprogram eller block , måste gränserna som definierar formen vara konstant uttryck. I andra fall kan en uttrycklig formuppsättning vara ett automatiskt objekt med hjälp av utsträckningar som kan variera vid varje anrop av ett delprogram eller block .

subroutine sub(n)
  integer, intent(in) :: n
  integer a(5)   ! A local explicit shape array with constant bound
  integer b(n)   ! A local explicit shape array, automatic object
end subroutine

Antagen form

En antagen formuppsättning är ett dummy-argument utan allocatable eller pointer . En sådan matris tar sin form från det faktiska argumentet som det är förknippat med.

integer a(5), b(10)
call sub(a)   ! In this call the dummy argument is like x(5)
call sub(b)   ! In this call the dummy argument is like x(10)

contains

  subroutine sub(x)
    integer x(:)    ! Assumed shape dummy argument
  end subroutine sub

end

När ett dummy-argument har antagit formen, ska proceduren som refererar till ha ett tydligt gränssnitt tillgängligt för den proceduren.

Antagad storlek

En antagen storleksgrupp är ett dummy-argument som har sin storlek antas från dess faktiska argument.

subroutine sub(x)
  integer x(*)   ! Assumed size array
end subroutine

Antagna storleksuppsättningar uppför sig mycket annorlunda än antagna formuppsättningar och dessa skillnader är dokumenterade någon annanstans.

Uppskjuten form

En uppskjuten form array är en matris som har den allocatable eller pointer attribut. Formen på en sådan matris bestäms av dess allokering eller pekartilldelning.

integer, allocatable :: a(:)
integer, pointer :: b(:)

Implicerad form

En implicit formuppsättning är en benämnd konstant som tar sin form från uttrycket som används för att fastställa dess värde

integer, parameter :: a(*) = [1,2,3,4]

Konsekvenserna av dessa arrayförklaringar på dummy-argumenter ska dokumenteras någon annanstans.


1 En teknisk specifikation som utvidgar Fortran 2008 lägger till en sjätte array-karaktär: antagen rang. Detta omfattas inte här.

2 Dessa kan på samma sätt skrivas som

integer, dimension(5) :: a
integer, dimension(:) :: b
integer, dimension(*) :: c

eller

integer a(5)
integer b(:)
integer c(*)

Hela matriser, arrayelement och arrayavsnitt

Betrakta den matris som förklaras som

real x(10)

Sedan har vi tre aspekter av intresse:

  1. Hela matrisen x ;
  2. Arrayelement, som x(1) ;
  3. Arrayavsnitt, som x(2:6) .

Hela matriser

I de flesta fall avser hela matrisen x alla elementen i matrisen som en enda enhet. Det kan visas i körbara uttalanden som print *, SUM(x) , print *, SIZE(x) eller x=1 .

En hel matris kan hänvisa till arrayer som inte är uttryckligen formade (till exempel x ovan):

function f(y)
  real, intent(out) :: y(:)
  real, allocatable :: z(:)

  y = 1.         ! Intrinsic assignment for the whole array
  z = [1., 2.,]  ! Intrinsic assignment for the whole array, invoking allocation
end function

En antagen storleksanordning kan också visas som en hel matris, men endast i begränsade omständigheter (för att dokumenteras någon annanstans).

Arrayelement

Ett arrayelement hänvisas till att ge heltalindex, ett för varje rangordning i arrayen, som anger platsen i hela arrayen:

real x(5,2)
x(1,1) = 0.2
x(2,4) = 0.3

Ett arrayelement är en skalär.

Arrayavsnitt

En matrisavsnitt är en hänvisning till ett antal element (kanske bara ett) i en hel matris med en syntax som involverar kolon:

real x(5,2)
x(:,1) = 0.         ! Referring to x(1,1), x(2,1), x(3,1), x(4,1) and x(5,1)
x(2,:) = 0.         ! Referring to x(2,1), x(2,2)
x(2:4,1) = 0.       ! Referring to x(2,1), x(3,1) and x(4,1)
x(2:3,1:2) = 0.     ! Referring to x(2,1), x(3,1), x(2,2) and x(3,2)
x(1:1,1) = 0.       ! Referring to x(1,1)
x([1,3,5],2) = 0.   ! Referring to x(1,2), x(3,2) and x(5,2)

Den sista formen ovan använder ett vektornivå . Detta är föremål för ett antal begränsningar utöver andra matrisavsnitt.

Varje matrisavsnitt är i sig själv en matris, även när det bara refereras till ett element. Det vill x(1:1,1) är en matris av rang 1 och x(1:1,1:1) är en matris med rang 2.

Arrayavsnitt har i allmänhet inte ett attribut för hela matrisen. I synnerhet var

real, allocatable :: x(:)
x = [1,2,3]     ! x is allocated as part of the assignment
x = [1,2,3,4]   ! x is dealloacted then allocated to a new shape in the assignment

uppgiften

x(:) = [1,2,3,4,5]   ! This is bad when x isn't the same shape as the right-hand side

är inte tillåtet: x(:) , även om en matrisdel med alla element i x , inte är en allokerbar matris.

x(:) = [5,6,7,8]

är bra när x har formen på höger sida.


Arraykomponenter i matriser

type t
   real y(5)
end type t

type(t) x(2)

Vi kan också hänvisa till hela matriser, arrayelement och arrayavsnitt i mer komplicerade inställningar.

Från ovanstående är x en hel matris. Vi har också

x(1)%y        ! A whole array
x(1)%y(1)     ! An array element
x%y(1)        ! An array section
x(1)%y(:)     ! An array section
x([1,2]%y(1)  ! An array section
x(1)%y(1:1)   ! An array section

I sådana fall får vi inte ha mer än en del av referensen som består av en grupp av rang 1. Följande till exempel är inte tillåtna

x%y             ! Both the x and y parts are arrays
x(1:1)%y(1:1)   ! Recall that each part is still an array section

Array-operationer

På grund av dess beräkningsmål är matematiska operationer på matriser rakt fram i Fortran.

Addition och subtraktion

Funktioner på matriser av samma form och storlek liknar mycket matrisalgebra. I stället för att gå igenom alla index med slingor kan man skriva tillägg (och subtraktion):

real, dimension(2,3) :: A, B, C
real, dimension(5,6,3) :: D
A    = 3.    ! Assigning single value to the whole array
B    = 5.    ! Equivalent writing for assignment
C    = A + B ! All elements of C now have value 8.
D    = A + B ! Compiler will raise an error. The shapes and dimensions are not the same

Matriser från skivning är också giltiga:

integer :: i, j
real, dimension(3,2) :: Mat = 0.
real, dimension(3)   :: Vec1 = 0., Vec2 = 0., Vec3 = 0.
i = 0
j = 0
do i = 1,3
  do j = 1,2
    Mat(i,j) = i+j
  enddo
enddo
Vec1 = Mat(:,1)
Vec2 = Mat(:,2)
Vec3 = Mat(1:2,1) + Mat(2:3,2)

Fungera

På samma sätt kan de flesta inneboende funktioner användas implicit under antagande av komponentvis funktion (även om detta inte är systematiskt):

real, dimension(2) :: A, B
A(1) = 6
A(2) = 44 ! Random values
B    = sin(A) ! Identical to B(1) = sin(6), B(2) = sin(44).

Multiplikation och uppdelning

Man måste vara försiktig med produkt och division: inneboende funktioner med * och / symboler är elementmässigt:

real, dimension(2) :: A, B, C
A(1) = 2
A(2) = 4
B(1) = 1
B(2) = 3
C = A*B ! Returns C(1) = 2*1 and C(2) = 4*3

Detta får inte misstas med matrisoperationer (se nedan).

Matrisoperationer

Matrisoperationer är inneboende procedurer. Till exempel är matrisprodukten för matriserna i föregående avsnitt skrivet enligt följande:

real, dimension(2,1) :: A, B
real, dimension(1,1) :: C
A(1) = 2
A(2) = 4
B(1) = 1
B(2) = 3
C = matmul(transpose(A),B) ! Returns the scalar product of vectors A and B

Komplexa funktioner tillåter inkapslade funktioner genom att skapa tillfälliga matriser. Medan vissa kompilatorer och kompileringsalternativ tillåts rekommenderas detta inte. En produkt som inkluderar en matristranspon kan till exempel skrivas:

real, dimension(3,3) :: A, B, C
A(:) = 4
B(:) = 5
C = matmul(transpose(A),matmul(B,matmul(A,transpose(B)))) ! Equivalent to A^t.B.A.B^T

Avancerade matrisavsnitt: prenumerationstripletter och vektorabonnemang

Som nämnts i ett annat exempel kan det hänvisas till en delmängd av elementen i en matris, kallad en matrisdel. Från det exemplet vi kan ha

real x(10)
x(:)   = 0.
x(2:6) = 1.
x(3:4) = [3., 5.]

Arrayavsnitt kan dock vara mer generella än detta. De kan ha formen av prenumerationstripletter eller vektorabonnemang.

Prenumerations tripletter

En prenumerationstrippel har formen [bound1]:[bound2][:stride] . Till exempel

real x(10)
x(1:10) = ...   ! Elements x(1), x(2), ..., x(10)
x(1:) = ...     ! The omitted second bound is equivalent to the upper, same as above
x(:10) = ...    ! The omitted first bound is equivalent to the lower, same as above
x(1:6:2) = ...  ! Elements x(1), x(3), x(5)
x(5:1) = ...    ! No elements: the lower bound is greater than the upper
x(5:1:-1) = ... ! Elements x(5), x(4), x(3), x(2), x(1)
x(::3) = ...    ! Elements x(1), x(4), x(7), x(10), assuming omitted bounds
x(::-3) = ...   ! No elements: the bounds are assumed with the first the lower, negative stride

När en steg (som inte får vara noll) anges börjar sekvensen med element med den första angivna gränsen. Om steget är positivt (resp. Negativt) tas de valda elementen efter en sekvens ökad (resp. Dekrementerad) av steget tills det sista elementet som inte är större (resp. Mindre) än den andra gränsen tas. Om steget utelämnas behandlas det som ett.

Om den första gränsen är större än den andra gränsen, och steget är positivt, anges inga element. Om den första gränsen är mindre än den andra gränsen, och steget är negativt, anges inga element.

Det bör noteras att x(10:1:-1) inte är samma som x(1:10:1) även om varje element i x visas i båda fallen.

Vectorabonnemang

Ett vektornivå är en rangordning med ett heltal. Detta anger en sekvens av element som motsvarar värdena i matrisen.

real x(10)
integer i
x([1,6,4]) = ...     ! Elements x(1), x(6), x(4)
x([(i,i=2,4)]) = ... ! Elements x(2), x(3) and x(4)
print*, x([2,5,2])   ! Elements x(2), x(5) and x(2)

Ett matrisavsnitt med ett vektornivå är begränsat i hur det kan användas:

  • det kan inte vara ett argument som är associerat med ett dummy-argument som definieras i proceduren;
  • det kanske inte är målet i ett uttalande om tilldelning av pekare;
  • det kanske inte är en intern fil i ett dataöverföringsuttalande.

Vidare kan en sådan matrisdel inte visas i ett uttalande som innebär dess definition när samma element väljs två gånger. Från ovan:

print*, x([2,5,2])   ! Elements x(2), x(5) and x(2) are printed
x([2,5,2]) = 1.      ! Not permitted: x(2) appears twice in this definition

Sektioner med högre rangordning

real x(5,2)
print*, x(::2,2:1:-1)  ! Elements x(1,2), x(3,2), x(5,2), x(1,1), x(3,1), x(5,1)


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow