Lehetséges lokális tömbök definiálása a Fortran szubprogramokban, de nem ez a jellemzõ. Ehelyett inkább az összes tömböt és dimenziójukatm már a fõprogramban deklaráljuk, és ezekre alkalmazzuk a segédprogramokat.
y := alpha*x + yahol alpha skalár, de x és y vektor. Nézzünk egy egyszerûbb subroutine-t, felhasználva a fentit::
subroutine saxpy (n, alpha, x, y) integer n real alpha, x(*), y(*) c c Saxpy: Szamold ki y := alpha*x + y, c ahol x és y n hosszusagu vektorok c c lokalis valtozok integer i c do 10 i = 1, n y(i) = alpha*x(i) + y(i) 10 continue c return endAz újdonságot a deklarációban megjelenõ csillagok jelentik: x(*) és y(*). Ezzel a jelöléssel az x és y vektorunk hossza tetszõleges lehet. Ennek elõnye, hogy ugyanazon segédprogramokat használhatjuk a különféle hosszúságú vektorokra. Utalva arra, hogy a Fortran call-by-reference típusú hivatkozáson alkalmazza, nem szükséges további memóriahelyeket lefoglalni, a segédprogram is a hívó programban definiált tömb elemein dolgozik.A programozó felelõssége az x és y vektorok hosszának helyes megválasztása, azaz hogy a program semelyik részén se forduljon elõ a vektor nem létezö elemére (megengedett elemszámnál nagyobb értékû helyre) való hivatkozás. Ennek elmulasztása gyakran visszatérõ hibának tûnik.
Így definiálhatunk a tömböket :
real x(n), y(n)A legtöbb programozó inkább a csillagos x(*) jelölést kedveli, hiszen nem mindig tudni elõre, hogy milyen hosszúságú vektorok kellenek majd. Néhány régebbi Fortran 77 programban ilyen deklarációt is láthatunk:
real x(1), y(1)Megtévesztõ lehet, de ez a jelölés akkor is helyes, ha a tömb mérete nagyobb, mint 1. Lehetõleg kerüljük e jelölés használatát.
subroutine matvec (m, n, A, lda, x, y) integer m, n, lda real x(*), y(*), A(lda,*) c c szamold ki: y = A*x, ahol A egy (m x n) matrix c Az A fodimenzioja lda c c Lokalis valtozok integer i, j c Induljon y do 10 i = 1, m y(i) = 0.0 10 continue c Matrix-vektor szorzas eredmenye a saxpy segitsegevel A oszlopaira c Fontos, az egyes oszlopk hossza m es nem n! do 20 j = 1, n call saxpy (m, x(j), A(1,j), y) 20 continue return endNéhány megjegyzést kell tennünk. A mátrix méretét (itt n és m) általánosan is megválaszthatjuk a csillagos kóddal, de a fõdimenziót továbbra is pontosan kell definiálni. Miért? Mert a (máshol változtatható méretre vonatkozó) * jelölés ebben az esetben a tömb utolsó dimenziójára alkalmazható. Erre magyarázatot a Fortran 77 sokdimenziós tömbtárolási mechanizmusa adhat (lsd a tömbökrõl szóló fejezetet)
Amikor kiszámítjuk a saxpy operátorral az y = A*x by értéket, szükségünk van A oszlopainak értékeire is. Az A mátrix j-edik oszlopa A(1:m,j). Azonban a Fortran 77 nem tudja kezelni ezt az összetett indexezést (a Fortran 90 már igen!). Ezért szükségünk van egy közelítésre, a mutatóvektorra, amivel az oszlop elsõ elemére A(1,j) hivatkozunk. (nem pontos a fogalom, de a megértést segítheti). Tudjuk, hogy a következõ memóriahelyeken, ezen oszlop elemei lesznek. A saxpy segédprogram az A(1,j)-t egy vektor elsõ elemének fogja kezelni, mit sem tudva arról, hogy ebben az esetben ez a vektor egy mátrix oszlopát jelenti.
Végül azt is meg kell jegyeznünk, hogy a konvenció alapján a mátrixok m sorból és n oszlopból állnak. Az i indexet sorindexként (1-tõl m-ig), a j indexet oszlopindexként (1-tõl n-ig) használjuk. A legtöbb lineáris algebrás számításra írt Fortran-program ezeket a jelöléseket használja, ami megkönnyíti a programszöveg olvasását.
Nézzünk egy könnyen érthetõ példát. A másik alapvetõ vektromûvelet a nyújtás (=skale), amikor a vektor minden elemét egy konstans számmal megszorozzuk. Ez programnyelven így szól:
subroutine scale(n, alpha, x) integer n real alpha, x(*) c c Lokalis valtozok integer i do 10 i = 1, n x(i) = alpha * x(i) 10 continue return endMiután megkaptuk az m x n -es mátrixunkat, meg szerenénk "nyújtani". Ahelyett, hogy erre is írnánk egy másik segédprogramot, elég ezt a mátrixok vektorként kezelve megnyújtani, alkalmazva a scale subroutine-t. Kézenfekvõ az alábbi metódus:
integer m, n parameter (m=10, n=20) real alpha, A(m,n) c Nehany utasitassal defininalni az A-t... c Most megnyujtjuk A-t call scale(m*n, alpha, A)Fontos megjegyezni, hogy a fenti példa mûködik, mert az eredetileg deklarált dimenziója A-nak megegyezik, azzal a mátrixéval, amiben éppen (számítás közben) tároljuk az A-t. Ha ez nem így van, akkor a fenti metódus nem jó. Rendszerint e kétfajta mátrix dimenzió nem egyezik meg, ilyenkor körültekintõen kell eljárnunk.Ebben az esetben a programunk így lesz korrekt:
subroutine mscale(m, n, alpha, A, lda) integer m, n, lda real alpha, A(lda,*) c c Lokalis valtozok integer j do 10 j = 1, n call scale(m, alpha, A(1,j) ) 10 continue return endÍgy már minden esetben mûködõképes lesz a programunk: a számításhoz szükségtelen sorok és oszlopok (amivel nagyobb az eredeti mátrix, mint az aktuális) elemeihez nem nyúl.
Copyright © 1995-7 by Stanford University. All rights reserved.
Fordították: Seres András Tamás és Szalai Szilvia (ELTE-TTK)