Appendix 5. Inbyggda funktioner och subrutiner i Fortran 95

A 5.0 Inledning

Det finns i Fortran 90 ett mycket stort antal inbyggda funktioner, och fem inbyggda subrutiner.

Detta avsnitt bygger på sektion 13 av standarden ISO (1991), vilken innehåller en mer formell framställning. Jag följer standardens gruppering av de olika funktionerna, men ger förklaringen direkt i anslutning till listan. För en mer uttömmande framställning hänvisar jag till Metcalf och Reid (1990, 1992).

När en parameter nedan är frivillig så har den getts med små bokstäver, gemena. När en argumentlista innehåller flera argument kan funktionen anropas antingen med positionsrelaterade argument eller med nyckelord, eller en kombination. Nyckelord måste användas om något föregående argument utelämnas, samt när man gett ett argument med nyckelord måste även alla följande ges med nyckelord. Nyckelord är de namn som getts med gemena nedan. Jag har däremot försvenskat några av de obligatoriska parametrarna, som ändrat ARRAY till FAELT. Jag har inte alltid gett alla naturliga inskränkningar i variablers tillåtna värden, som att rangen ej får vara negativ.

A 5.1 Funktion som undersöker om ett visst argument finns i anropslistan.

PRESENT(A) 
Returnerar .TRUE. om argumentet A är med i anropslistan, .FALSE. annars. Användningen illustreras i avsnitten 5.2.1.6 och 11.7.

A 5.2 Numeriska funktioner

Följande numeriska funktioner kommer från Fortran 77:

ABS, AIMAG, AINT, ANINT, CMPLX, CONJG, DBLE, DIM, DPROD, INT, MAX, MIN, MOD, NINT, REAL och SIGN.

Vissa av dessa kan nu kompletteras med en slags-parameter av typ AINT(A,kind), nämligen AINT, ANINT, CMPLX, INT, NINT och REAL, samt från Fortran 95 även de nya CEILING och FLOOR.

Dessutom har CEILING, FLOOR och MODULO tillkommit. Endast den senare är besvärlig att förklara, vilket bäst sker med ett exempel från ISO (1991). Både MOD och MODULO ger naturligtvis resten vid heltalsdivision, men de behandlar tecknen i täljare och nämnare olika. Resultatet för funktionerna MOD och MODULO är odefinierat om det andra argumentet är noll.

        MOD(8,5)   ger  3 MODULO(8,5)   ger  3
        MOD(-8,5)  ger -3 MODULO(-8,5)  ger  2
        MOD(8,-5)  ger  3 MODULO(8,-5)  ger -2
        MOD(-8,-5) ger -3 MODULO(-8,-5) ger -3
En historisk relikt för de numeriska funktionerna är att de i Fortran 66 var tvingade att ha olika namn för olika precisioner, och dessa explicita namn är fortfarande de enda som kan användas då funktionerna användes som argument. En fullständig tabell över samtliga numeriska funktioner ges därför. De markerade med * får ej användas som argument. En del funktioner har två specifika namn, som INT och IFIX, vilka är helt likvärda. Jag använder nedan beteckningen C för komplext flyttal, D för flyttal i dubbel precision, I för heltal och R för flyttal i enkel precision. I samtliga fall förutsättes standard-slaget (KIND).
Uppgift           Generiskt     Specifikt    Data-typ
                  namn            namn       Arg   Res

Konvertering      INT           -            I     I
 till heltal                *   INT          R     I
                            *   IFIX         R     I
                            *   IDINT        D     I
 (av realdelen)                 -            C     I

Konvertering      REAL      *   REAL         I     R
 till flyttal               *   FLOAT        I     R
                                -            R     R
                            *   SNGL         D     R
 (realdelen)                    -            C     R

Konvertering      DBLE          -            I     D
 till dubbel                    -            R     D
 precision                      -            D     D
 (realdelen)                    -            C     D

Konvertering      CMPLX         -         I (2I)   C
 till komplex                   -         R (2R)   C
                                -         D (2D)   C
                                -            C     C

Trunkering        AINT          AINT         R     R
                                DINT         D     D

Avrundning        ANINT         ANINT        R     R
                                DNINT        D     D
                  NINT          NINT         R     I
                                IDNINT       D     I

Absolut           ABS           IABS         I     I
 värde                          ABS          R     R
                                DABS         D     D
                                CABS         C     R

Rest              MOD           MOD          2I    I
                                AMOD         2R    R
                                DMOD         2D    D
                  MODULO        -            2I    I
                                -            2R    R
                                -            2D    D

Golv              FLOOR         -            I     I
                                -            R     R
                                -            D     D

Tak               CEILING       -            I     I
                                -            R     R
                                -            D     D

Tecken-           SIGN          ISIGN        2I    I
 överföring                     SIGN         2R    R
                                DSIGN        2D    D

Positiv           DIM           IDIM         2I    I
 differens                      DIM          2R    R
                                DDIM         2D    D

Inre produkt      -             DPROD        R     D
 
Maximum           MAX       *   MAX0         I     I
                            *   AMAX1        R     R
                            *   DMAX1        D     D
                  -         *   AMAX0        I     R
                  -         *   MAX1         R     I

Minimum           MIN       *   MIN0         I     I
                            *   AMIN1        R     R
                            *   DMIN1        D     D
                  -         *   AMIN0        I     R
                  -         *   MIN1         R     I

Imaginärdel       -             AIMAG        C     R

Konjugering       -             CONJG        C     C
De flesta av de ovanstående funktionernas uppgift framgår ur namnet, men förutom ovan diskuterade MOD och MODULO behöver ytterligare några diskuteras. Trunkering sker mot noll, dvs INT(-3.7) blir -3, medan naturligtvis avrundning sker korrekt, dvs NINT(-3.7) blir -4. De båda nya funktionerna FLOOR och CEILING trunkerar mot - oändligheten respektive mot + oändligheten.

Funktionen CMPLX kan ha ett eller två argument, vid två argument måste dessa vara av samma typ och ej av typ COMPLEX.

Funktionen MOD(X,Y) beräknar X - INT(X/Y)*Y.

Teckenöverföringsfunktionen SIGN(X,Y) tar tecknet hos det andra argumentet och sätter det på det första, dvs ABS(X) om Y >= 0 och -ABS(X) om Y < 0.

I Fortran 95 infördes att teckenfunktionen använder tecknet hos det andra argumentet även om det första argumentet är noll.

Positiv differens DIM är en funktion jag aldrig använt, men DIM(X,Y) ger X-Y om detta är positivt och annars noll.

Inre produkt DPROD är däremot en mycket användbar funktion som ger produkten av två enkelprecisionstal som ett dubbelprecisionstal. Den är både snabb och noggrann.

De båda funktionerna MAX och MIN är unika i det att de har ett godtyckligt antal argument (av samma typ), dock minst två.

A 5.3 Matematiska funktioner

De trigonometriska funktionerna och deras inverser arbetar naturligtvis i radianer och ej i grader. Följande matematiska funktioner kommer från Fortran 77:

ACOS, ASIN, ATAN, ATAN2, COS, COSH, EXP, LOG, LOG10, SIN, SINH, SQRT, TAN och TANH.

En historisk relikt för de matematiska funktionerna är att dessa i Fortran 66 var tvingade att ha olika namn för olika precisioner, och dessa explicita namn är fortfarande de enda som kan användas då funktionerna användes som argument. En fullständig tabell över samtliga matematiska funktioner ges därför.

Uppgift           Generiskt     Specifikt    Data-typ
                  namn          namn         Arg   Res

Kvadratrot        SQRT          SQRT         R     R
                                DSQRT        D     D
                                CSQRT        C     C

Exponential-      EXP           EXP          R     R
 funktionen                     DEXP         D     D
                                CEXP         C     C

Naturlig-         LOG           ALOG         R     R
 logaritm                       DLOG         D     D
                                CLOG         C     C

10-logaritmen     LOG10         ALOG10       R     R
                                DLOG10       D     D

Sinus             SIN           SIN          R     R
                                DSIN         D     D
                                CSIN         C     C

Cosinus           COS           COS          R     R
                                DCOS         D     D
                                CCOS         C     C

Tangent           TAN           TAN          R     R
                                DTAN         D     D

Arcus-sinus       ASIN          ASIN         R     R
                                DASIN        D     D

Arcus-cosinus     ACOS          ACOS         R     R
                                DACOS        D     D

Arcus-            ATAN          ATAN         R     R
 tangenten                      DATAN        D     D
                  ATAN2         ATAN2        2R    R
                                DATAN2       2D    D

Hyperbolisk       SINH          SINH         R     R
 Sinus                          DSINH        D     D

Hyperbolisk       COSH          COSH         R     R
 Cosinus                        DCOSH        D     D

Hyperbolisk       TANH          TANH         R     R
 Tangent                        DTANH        D     D
De flesta av de ovanstående funktionernas uppgift framgår ur namnet, men några behöver diskuteras. Notera först att ingen av dessa är definierad för heltalsargument, varför man inte kan beräkna exempelvis kvadratroten ur heltalet 4 med SQRT(4), men väl med NINT(SQRT(REAL(4))). Notera vidare att samtliga komplexa funktioner returnerar principalvärdet.

Kvadratroten ger ett reellt resultat för argument i enkel eller dubbel precision, och ett komplext resultat för ett komplext argument. Så ger SQRT(-1.0) en felutskrift (oftast redan vid kompileringen), medan man får den komplexa (rent imaginära) roten med följande satser.

        COMPLEX, PARAMETER    :: MINUS_ETT = -1.0
        COMPLEX                 :: Z
        Z = SQRT(MINUS_ETT)
Argumentet för de "vanliga" logaritmerna måste vara positivt, medan argument för CLOG måste vara skilt från noll. Värdet kommer att ligga i intervallet (-pi; pi], det blir p endast om argumentet har negativ realdel och imaginärdel noll.

Argumentet för ASIN måste till beloppet vara högst ett. Funktionens värde kommer att ligga i intervallet [-pi/2; pi/2].

Argumentet för ACOS måste till beloppet vara högst ett. Funktionens värde kommer att ligga i intervallet [0; pi].

Funktionen ATAN kommer att få ett värde i intervallet [-pi/2; pi/2].

Funktionen ATAN2(Y,X) = arctan(y/x) kommer att få ett värde i intervallet (-pi; pi]. Om Y är positivt blir resultatet positivt. Om Y är noll blir resultatet noll om X är positivt och pi om X är negativt. Om Y är negativt blir resultatet negativt. Om X är noll blir resultatet ±pi/2. De båda argumenten X och Y får ej samtidigt vara noll. Syftet med funktionen är att undvika division med noll vid vinkelberäkningen.

En naturlig begränsning för de matematiska funktionerna beror på den begränsade noggrannheten, vilket innebär att exponentialfunktionen EXP ger spill eller bottning redan vid "måttliga" värden på argumentet, och att de trigonometriska funktionerna får mycket låg noggrannhet vid till beloppet stora argument. Dessa begränsningar är implementationsberoende, och bör vara angivna i respektive maskins manual.

A 5.4 Textsträngsfunktioner

Nedanstående funktioner utför operationer från och till textsträngar. Notera att ACHAR arbetar med det standardiserade ASCII-teckensättet, medan CHAR arbetar med den aktuella representationen i datorn.
ACHAR(I)              Ger det ASCII-tecken som har nr I
ADJUSTL(STRING)       Vänsterjusterar
ADJUSTR(STRING)       Högerjusterar
CHAR(I,kind)          Ger det tecken som har nr I
IACHAR(C)             Ger ASCII-numret för tecknet C
ICHAR(C)              Ger numret för tecknet C

INDEX(STRING,SUBSTRING,back)
                      Ger startpositionen för en
                      delsträng inom en sträng.
                      Om BACK är sant erhålles den
                      sista förekomsten, annars
                      den första.

LEN_TRIM(STRING)      Ger längden av en sträng utan
                      de eventuellt avslutande blanka.

LGE(STRING_A,STRING_B)
LGT(STRING_A,STRING_B)
LLE(STRING_A,STRING_B)
LLT(STRING_A,STRING_B)
REPEAT(STRING,NCOPIES)    Konkatenerar en sträng NCOPIES
                          gånger med sig själv.
SCAN(STRING,SET,back)     Ger positionen för den första 
                          förekomsten av något tecken i SET
                          i strängen STRING. Om BACK är sant
                          i stället sista!
TRIM(STRING)              Ger strängen STRING utan avslutande
                          blanka.
VERIFY(STRING,SET,back)   Ger positionen i STRING för det
                          första tecken i STRING som ej 
                          finns i SET. Om BACK är sant 
                          i stället sista! 
                          Resultatet är 0 om alla finns!

A 5.5 Textsträngsfunktion för förfrågan

LEN(STRING)
Denna rutin ger längden av en textsträng. Strängen behöver ej ha tilldelats något värde.

A 5.6 Slagsfunktioner

KIND(X)
SELECTED_INT_KIND(R)
SELECTED_REAL_KIND(p,r)
Den första ger slaget av aktuellt argument, som kan vara av typ INTEGER, REAL, COMPLEX, LOGICAL eller CHARACTER. Argumentet X behöver ej ha tilldelats något värde.

Den andra ger ett heltalsslag med önskat antal siffror, och den tredje ett flyttalsslag med numerisk precision minst P siffror och en (fiktiv) decimal exponent mellan -R och +R. Parametrarna P och R måste vara skalära heltal. Minst en av P och R måste ges.

Resultatet av SELECTED_INT_KIND är heltal från 0 och uppåt, om önskat slag ej finns returneras i stället -1. Om flera implementerade typer satisfierar villkoret användes den med minsta decimala exponent, om flera sådana den med minsta slag (nummer). Resultatet av SELECTED_REAL_KIND är heltal från 0 och uppåt, om önskat slag ej finns returneras i stället -1 om precisionen ej finns, -2 om exponenten inte finns, och -3 om ingen finns. Om flera implementerade typer satisfierar villkoren användes den med minsta decimala precision, om flera sådana den med minsta slag (nummer).

Exempel på användning av KIND finns i kapitel 10, avsnitt 3 och kapitel 10, avsnitt 4. Exempel på slag i olika implementationer ges i Appendix 6 för NAG och Appendix 7 för Cray.

A 5.7 Logisk funktion

LOGICAL(L,kind)
Omvandlar mellan olika slag av logiska variabler.

A 5.8 Numeriska förfrågningsfunktioner

Dessa funktioner arbetar i en viss modell av heltals- respektive flyttalsaritmetik, se ISO (1991), avsnitt 13.7.1. Funktionerna ger egenskaper hos tal av samma slag som variabeln X, den kan vara REAL och i vissa fall INTEGER. Funktioner som ger egenskaper hos just argumentet X finns under punkt 12 Flyttals-manipuleringsfunktioner.
DIGITS(X)       Antalet signifikanta bitar
EPSILON(X)      Det minsta positiva talet som
                adderat till 1 ger ett tal
                som är större än 1
HUGE(X)         Det största positiva talet
MAXEXPONENT(X)  Den största exponenten
MINEXPONENT(X)  Den minsta exponenten
PRECISION(X)    Decimala precisionen
RADIX(X)        Basen i modellen
RANGE(X)        Decimal exponent
TINY(X)         Det minsta positiva talet

A 5.9 Bitförfrågningsfunktion

BIT_SIZE(I)
Returnerar antalet bitar enligt modellen för bit-representation i standarden ISO (1991), avsnitt 13.5.7. Normalt erhålles antalet bitar i ett helord.

A 5.10 Bitmanipuleringsfunktioner

Här användes modellen för bit-representation i standarden ISO (1991), avsnitt 13.5.7.
BTEST(I,POS)         TRUE om position nr POS av I är 1
IAND(I,J)            Logisk addition av bitmönstren i I och J
IBCLR(I,POS)         Nollställer biten i position POS
IBITS(I,POS,LEN)     Använder LEN bitar av ordet I
                     med början i position POS,
                     övriga bitar nollställes; 
                     POS + LEN <= BIT_SIZE(I)
IBSET(I,POS)         Sätter biten i position POS till 1
IEOR(I,J)            Utför logiskt exklusivt eller
IOR(I,J)             Utför logisk eller
ISHFT(I,SHIFT)       Utför logiskt skift ett antal steg,
                     åt höger om SHIFT < 0
                     åt vänster om SHIFT > 0
                     Nollor införes på lediga positioner
ISHFTC(I,SHIFT,size) Utför logiskt skift ett antal steg,
                     cirkulärt åt höger om SHIFT < 0
                     cirkulärt åt vänster om SHIFT > 0
                     Om SIZE finns med gäller
                     0 < SIZE <= BIT_SIZE(I)
                     Skift sker bara för de bitar som
                     finns i de SIZE högraste 
                     positionerna, men alla om SIZE saknas.
NOT(I)               Utför logiskt komplement

A 5.11 Transferfunktion

TRANSFER(SOURCE,MOULD,size)
Denna funktion specificerar att den fysiska representationen av det första argumentet SOURCE skall behandlas som om det hade typ och parametrar som det andra MOULD, men utan att konverteras. Ändamålet är att erbjuda en möjlighet att flytta en storhet av en viss typ via en rutin som saknar just denna typ.

A 5.12 Flyttals-manipuleringsfunktioner

Dessa funktioner arbetar i en viss modell av heltals- respektive flyttalsaritmetik, se standarden ISO (1991), avsnitt 13.7.1. Funktionerna ger tal relaterade till aktuell variabel X av typ REAL. Funktioner som ger egenskaper hos tal av samma slag som variabeln X finns under punkt 8, Numeriska förfrågningsfunktioner.
EXPONENT(X)        Talets exponent
FRACTION(X)        Talets bråkdel
NEAREST(X,S)       Ger nästa representerbara tal
                   i angiven riktning (tecknet hos S)
RRSPACING(X)       Inverterade värdet av avståndet
                   mellan två tal i omgivningen
SCALE(X,I)         Multiplicerar X med basen upphöjd till I
SET_EXPONENT(X,I)  Ger det tal som har bråkdelen hos X
                   och exponenten I
SPACING(X)         Avståndet mellan två tal i
                   omgivningen

A 5.13 Vektor- och matrismultiplikationsfunktioner

DOT_PRODUCT(VEKTOR_A,VEKTOR_B)
Skapar skalärprodukten av två vektorer, vilka måste ha samma längd.
MATMUL(MATRIS_A,MATRIS_B)
Skapar matrisprodukten av två matriser, vilka måste vara konsistenta, dvs ha dimensionering (M,K) respektive (K,N). Användes i kapitel 4, avsnitt 4.4.1.

A 5.14 Fältfunktioner

ALL(MASK,dim)
Skapar ett logiskt värde som anger om alla relationer i MASK är sanna, eventuellt bara längst önskad dimension.
ANY(MASK,dim)
Skapar ett logiskt värde som anger om någon relation i MASK är sann, eventuellt bara längst önskad dimension.
COUNT(MASK,dim)
Returnerar ett numeriskt värde som anger antalet relationer i MASK som är sanna, eventuellt bara längst önskad dimension.
MAXVAL(FAELT,dim,mask)
Returnerar det största värdet i fältet FAELT, eventuellt bara av de som uppfyller relationen i MASK, eventuellt bara längst önskad dimension.
MINVAL(FAELT,dim,mask)
Returnerar det minsta värdet i fältet FAELT, eventuellt bara av de som uppfyller relationen i MASK, eventuellt bara längst önskad dimension.
PRODUCT(FAELT,dim,mask)
Skapar produkten av alla element i fältet FAELT, eventuellt bara längst önskad dimension, eventuellt utnyttjande MASK för att bestämma vilka element som skall vara med.
SUM(FAELT,dim,mask)
Returnerar summan av alla element i fältet FAELT, eventuellt bara av de som uppfyller relationen i MASK, eventuellt bara längst önskad dimension. Exempel finns i Appendix 3, punkt 11.

A 5.15 Fältförfrågningsfunktioner

Se även Appendix 3, punkt 10 och punkt 11.
ALLOCATED(FAELT)
Logisk funktion som talar om ifall fältet FAELT är allokerat.
LBOUND(FAELT,dim)
Funktion som ger de lägre dimensioneringsgränserna för FAELT, om DIM ej är med erhålles en heltalsvektor, om DIM är med erhålles ett heltal med just den lägre dimensioneringsgränsen, för just den dimensionen.
SHAPE(SOURCE)
Funktion som ger mönstret för ett fält SOURCE som en heltalsvektor.
SIZE(FAELT,dim)
Funktion som ger antalet element i ett fält FAELT om DIM saknas, och antalet element i aktuell dimension om DIM finns.
UBOUND(FAELT,dim)
Funktion som ger de övre dimensioneringsgränserna för FAELT, om DIM ej är med erhålles en heltalsvektor, om DIM är med erhålles ett heltal med just den högre dimensioneringsgränsen, för just den dimensionen.

A 5.16 Fältkonstruktionsfunktioner

MERGE(TSOURCE,FSOURCE,MASK)
Funktion som förenar två fält, den ger elementet i TSOURCE om villkoret i MASK är sant och elementet i FSOURCE om det är falskt. De båda fälten TSOURCE och FSOURCE måste ha samma typ och mönster. Resultatet blir likaså av denna typ och mönster. Även MASK måste ha samma mönster.

Jag ger här ett ganska omfattande exempel på användning av MERGE, vilket även utnyttjar RESHAPE från nästa avsnitt för att bygga upp lämpliga testmatriser.

   IMPLICIT NONE
   INTERFACE
       SUBROUTINE SKRIV (A)
          REAL :: A(:,:)
       END SUBROUTINE SKRIV
       SUBROUTINE LSKRIV (A)
          LOGICAL :: A(:,:)
       END SUBROUTINE LSKRIV
   END INTERFACE

   REAL, DIMENSION(2,3)     :: TSOURCE, FSOURCE, RESULT
   LOGICAL,  DIMENSION(2,3) :: MASK 
   TSOURCE = RESHAPE( (/ 11, 21, 12, 22, 13, 23 /), &
                      (/ 2,3 /) )
   FSOURCE = RESHAPE( (/ -11, -21, -12, -22, -13, -23 /), &
                      (/ 2,3 /) )
   MASK = RESHAPE( (/ .TRUE., .FALSE., .FALSE., .TRUE.,&
                      .FALSE., .FALSE. /), (/ 2,3 /) )

   RESULT = MERGE(TSOURCE, FSOURCE, MASK)
   CALL SKRIV(TSOURCE)
   CALL SKRIV(FSOURCE)
   CALL LSKRIV(MASK)
   CALL SKRIV(RESULT)
   END

   SUBROUTINE SKRIV (A)
   REAL :: A(:,:)
   DO I = LBOUND(A,1), UBOUND(A,1)
      WRITE(*,*) ( A(I,J), J = LBOUND(A,2), UBOUND(A,2) )
   END DO
   RETURN
   END SUBROUTINE SKRIV

   SUBROUTINE LSKRIV (A)
   LOGICAL :: A(:,:)
   DO I = LBOUND(A,1), UBOUND(A,1)
      WRITE(*,"(8L12)") (A(I,J), J = LBOUND(A,2), UBOUND(A,2))
   END DO
   RETURN
   END SUBROUTINE LSKRIV
Utmatningen blir följande:
  11.0000000  12.0000000  13.0000000
  21.0000000  22.0000000  23.0000000

 -11.0000000 -12.0000000 -13.0000000
 -21.0000000 -22.0000000 -23.0000000

           T           F           F
           F           T           F

  11.0000000 -12.0000000 -13.0000000
 -21.0000000  22.0000000 -23.0000000
PACK(FAELT,MASK,vector)
Packar ett fält till en vektor under kontroll av MASK. Mönstret hos det logiska fältet MASK måste överensstämma med det för FAELT eller vara skalär. Om VECTOR är med måste den vara ett fält av rang 1 (dvs en vektor) med minst lika många element som är sanna i MASK, och ha samma typ som FAELT. Om MASK är en skalär med värdet sant måste VECTOR i stället ha minst lika många element som FAELT.

Resultatet blir en vektor med lika många element som de som i FAELT uppfyller villkoret om VECTOR saknas (dvs alla om MASK är en skalär med värdet sant), i annat fall lika många som i VECTOR. Värdena blir de godkända (dvs som uppfyller villkoret) i FAELT tagna i vanlig Fortran-ordning, om VECTOR är med och längre fylls det på med de värdena (oförändrad plats).

Det följande exemplet är baserat på en modifiering av det för MERGE, men jag ger nu bara resultatet.

        FAELT
          11.0000000  12.0000000  13.0000000
          21.0000000  22.0000000  23.0000000

        VEKTOR
         -11.0000000
         -21.0000000
         -12.0000000
         -22.0000000
         -13.0000000
         -23.0000000

        MASK
           T           F           F
           F           T           F

        PACK(FAELT, MASK)
          11.0000000
          22.0000000

        PACK(FAELT, MASK, VEKTOR)
          11.0000000
          22.0000000
         -12.0000000
         -22.0000000
         -13.0000000
         -23.0000000
SPREAD(SOURCE,DIM,NCOPIES)
Funktionen SPREAD (SOURCE, DIM, NCOPIES) returnerar ett fält av samma typ som argumentet SOURCE, men med rangen ökad med ett. Parametrarna DIM och NCOPIES är heltal. Om NCOPIES är negativ så användes i stället värdet noll. Om SOURCE är en skalär så blir SPREAD helt enkelt en vektor med NCOPIES element som alla har samma värde som SOURCE. Parametern DIM anger vilket index som skall utökas, det måste vara mellan 1 och 1+(rangen hos SOURCE), om SOURCE är en skalär måste således DIM vara ett. Parametern NCOPIES ger antalet element i den nya dimensionen, således ej antalet nya kopior. Ytterligare diskussion i lösningen till övning (4.1).
UNPACK(VECTOR,MASK,FAELT)
Sprider en vektor till ett fält under kontroll av MASK. Mönstret hos det logiska fältet MASK måste överensstämma med det för FAELT. Fältet VECTOR måste ha rang 1 (dvs vara en vektor) med minst lika många element som är sanna i MASK, och ha samma typ som FAELT. Om FAELT ges som en skalär betraktas det som ett fält med samma mönster som MASK och samma skalära element överallt.

Resultatet blir ett fält med samma mönster som MASK, och samma typ som VECTOR. Värdena blir de från VECTOR för godkända (dvs som uppfyller villkoret i MASK) tagna i vanlig Fortran-ordning, medan övriga positioner i FAELT behåller sina gamla värden.

A 5.17 Fältomvandlingsfunktion

RESHAPE(SOURCE,SHAPE,pad,order)
Konstruerar ett fält med specificerat mönster SHAPE utgående från elementen i ett givet fält SOURCE. Om PAD saknas måste storleken på SOURCE vara minst PRODUCT(SHAPE). Om PAD finns måste det ha samma typ som SOURCE. Om ORDER finns måste det vara INTEGER och ha samma mönster som SHAPE, och värdena måste vara en permutation av (1, 2, 3, ..., n), där n är antalet dimensioner i SHAPE, dvs högst 7.

Resultatet har naturligtvis ett mönster SHAPE, och elementen är de i SOURCE eventuellt kompletterade med PAD. De olika dimensionerna har permuterats vid tilldelningen av element om ORDER var med, men detta påverkar inte resultatets mönster. Exempel finns i Appendix 3, punkt 9. Ett mer avancerat exempel, som även behandlar de valfria argumenten, följer.

      PROGRAM TEST_OPTIONAL_ARGUMENTS_RESHAPE
      INTERFACE
          SUBROUTINE WRITE_MATRIX(A)
             REAL, DIMENSION(:,:) :: A
          END SUBROUTINE  WRITE_MATRIX
      END INTERFACE

      REAL, DIMENSION (1:9) :: B = (/ 11, 12, 13, &
                                      14, 15, 16, 17, 18, 19 /)
      REAL, DIMENSION (1:3, 1:3) :: C, D, E
      REAL, DIMENSION (1:4, 1:4) :: F, G, H
      INTEGER, DIMENSION (1:2) :: ORDER1 = (/ 1, 2 /)
      INTEGER, DIMENSION (1:2) :: ORDER2 = (/ 2, 1 /)
      REAL, DIMENSION (1:16)  :: PAD1 = &
          (/ -1, -2, -3, -4, -5, -6, -7, -8, &
             -9, -10, -11, -12, -13, -14, -15, -16 /)

      C = RESHAPE( B, (/ 3, 3 /) )
      CALL WRITE_MATRIX(C)

      D = RESHAPE( B, (/ 3, 3 /), ORDER = ORDER1)
      CALL WRITE_MATRIX(D)

      E = RESHAPE( B, (/ 3, 3 /), ORDER = ORDER2)
      CALL WRITE_MATRIX(E)

      F = RESHAPE( B, (/ 4, 4 /), PAD = PAD1)
      CALL WRITE_MATRIX(F)

      G = RESHAPE( B, (/ 4, 4 /), PAD = PAD1, ORDER = ORDER1)
      CALL WRITE_MATRIX(G)

      H = RESHAPE( B, (/ 4, 4 /), PAD = PAD1, ORDER = ORDER2)
      CALL WRITE_MATRIX(H)
      END PROGRAM TEST_OPTIONAL_ARGUMENTS_RESHAPE

      SUBROUTINE WRITE_MATRIX(A)
      REAL, DIMENSION(:,:) :: A
      WRITE(*,*)
      DO I = LBOUND(A,1), UBOUND(A,1)
      WRITE(*,*) (A(I,J), J = LBOUND(A,2), UBOUND(A,2))
      END DO
      END SUBROUTINE WRITE_MATRIX
Utmatningen av matriserna C, D och E blir
RESHAPE( B, (/ 3, 3 /) )
  11.0000000  14.0000000  17.0000000
  12.0000000  15.0000000  18.0000000
  13.0000000  16.0000000  19.0000000

RESHAPE( B, (/ 3, 3 /), ORDER = ORDER1)
  11.0000000  14.0000000  17.0000000
  12.0000000  15.0000000  18.0000000
  13.0000000  16.0000000  19.0000000

RESHAPE( B, (/ 3, 3 /), ORDER = ORDER2)
  11.0000000  12.0000000  13.0000000
  14.0000000  15.0000000  16.0000000
  17.0000000  18.0000000  19.0000000
Utmatningen av matriserna F, G och H (där man lagt till ytterligare en kolumn) blir
RESHAPE( B, (/ 4, 4 /), PAD = PAD1)
  11.0000000  15.0000000  19.0000000  -4.0000000
  12.0000000  16.0000000  -1.0000000  -5.0000000
  13.0000000  17.0000000  -2.0000000  -6.0000000
  14.0000000  18.0000000  -3.0000000  -7.0000000

RESHAPE( B, (/ 4, 4 /), PAD = PAD1, ORDER = ORDER1)
  11.0000000  15.0000000  19.0000000  -4.0000000
  12.0000000  16.0000000  -1.0000000  -5.0000000
  13.0000000  17.0000000  -2.0000000  -6.0000000
  14.0000000  18.0000000  -3.0000000  -7.0000000

RESHAPE( B, (/ 4, 4 /), PAD = PAD1, ORDER = ORDER2)
  11.0000000  12.0000000  13.0000000  14.0000000
  15.0000000  16.0000000  17.0000000  18.0000000
  19.0000000  -1.0000000  -2.0000000  -3.0000000
  -4.0000000  -5.0000000  -6.0000000  -7.0000000

A 5.18 Fältmanipuleringsfunktioner

Skiftfunktionerna lämnar mönstret av fältet oförändrat, men flyttar om elementen. De är så pass krångliga att jag rekommenderar studium även av standarden ISO (1991).
CSHIFT(FAELT,SHIFT,dim)
Utför cirkulärt skift SHIFT positioner åt vänster om SHIFT är positivt, åt höger om det är negativt. Om FAELT är en vektor sker skiftet på ett naturligt sätt, om det är ett fält av högre ordning sker skiftet på alla sektioner längs dimension DIM.

Om DIM saknas inträffar samma som om det vore 1, annars måste det ha ett skalärt heltalsvärde mellan 1 och n = rangen hos FAELT. Argumentet SHIFT är ett skalärt heltal om FAELT har rang 1, annars kan det vara ett skalärt heltal eller ett heltalsfält av rang n-1 och samma mönster som FAELT, utom längs dimensionen DIM (som bortfaller på grund av den lägre rangen). Olika sektioner kan således skiftas olika mycket och åt olika håll.

EOSHIFT(FAELT,SHIFT,boundary,dim)
Utför skift SHIFT positioner åt vänster om SHIFT är positivt, åt höger om det är negativt, i stället för utskiftade element tas element från BOUNDARY in på andra sidan. Om FAELT är en vektor sker skiftet på ett naturligt sätt, om det är ett fält av högre ordning sker skiftet på alla sektioner längs dimension DIM. Om DIM saknas inträffar samma som om det vore 1, annars måste det ha ett skalärt heltalsvärde mellan 1 och n = rangen hos FAELT. Argumentet SHIFT är ett skalärt heltal om FAELT har rang 1, annars kan det vara ett skalärt heltal eller ett heltalsfält av rang n-1 och med samma mönster som fältet FAELT, utom längs dimensionen DIM (som bortfaller på grund av den lägre rangen).

Motsvarande gäller BOUNDARY, som dock naturligtvis har samma typ som FAELT. Om parametern BOUNDARY saknas användes i stället lämpligt val av noll, .FALSE. eller blank beroende på datatyp. Olika sektioner kan således skiftas olika mycket och åt olika håll.

Ett enkelt exempel på ovanstående båda funktioner i vektorfallet följer.

        REAL, DIMENSION(1:6) :: A = (/ 11.0, 12.0, 13.0, 14.0, &
                                       15.0, 16.0 /)
        REAL, DIMENSION(1:6) :: X, Y
        WRITE(*,10) A
        X = CSHIFT ( A, SHIFT = 2)
        WRITE(*,10) X
        Y = CSHIFT ( A, SHIFT = -2)
        WRITE(*,10) Y
        X = EOSHIFT ( A, SHIFT = 2)
        WRITE(*,10) X
        Y = EOSHIFT ( A, SHIFT = -2)
        WRITE(*,10) Y
 10     FORMAT(1X,6F6.1)
        END
Utskriften blev följande.
   11.0  12.0  13.0  14.0  15.0  16.0
   13.0  14.0  15.0  16.0  11.0  12.0
   15.0  16.0  11.0  12.0  13.0  14.0
   13.0  14.0  15.0  16.0   0.0   0.0
    0.0   0.0  11.0  12.0  13.0  14.0
Ett enkelt exempel på ovanstående båda funktioner i matrisfallet följer. Jag har även här utnyttjat RESHAPE för att skapa en lämplig matris att utgå från.
   11.0  12.0  13.0   Z = RESHAPE( B, (/3,3/) )
   14.0  15.0  16.0   
   17.0  18.0  19.0   
 
   17.0  18.0  19.0   X = CSHIFT ( Z, SHIFT = 2)
   11.0  12.0  13.0   
   14.0  15.0  16.0   
 
   13.0  11.0  12.0   X = CSHIFT ( Z, SHIFT = 2, DIM = 2)
   16.0  14.0  15.0   
   19.0  17.0  18.0   
 
   14.0  15.0  16.0   X = CSHIFT ( Z, SHIFT = -2)
   17.0  18.0  19.0   
   11.0  12.0  13.0   
 
   17.0  18.0  19.0   X = EOSHIFT ( Z, SHIFT = 2)
    0.0   0.0   0.0   
    0.0   0.0   0.0   
 
   13.0   0.0   0.0   X = EOSHIFT ( Z, SHIFT = 2, DIM = 2)
   16.0   0.0   0.0   
   19.0   0.0   0.0   
 
    0.0   0.0   0.0   X = EOSHIFT ( Z, SHIFT = -2)
    0.0   0.0   0.0   
   11.0  12.0  13.0   
TRANSPOSE(MATRIS)
Transponerar en matris, dvs ett fält av rang 2. Den byter således rader och kolumner i en matris.

A 5.19 Lokaliseringsfunktioner

MAXLOC(FAELT,mask)
Returnerar positionen för det största elementet i fältet FAELT, eventuellt bara av de som uppfyller relationen i MASK. Resultatet kommer som en heltalsvektor! Användes i lösningen till övning (4.1).
MINLOC(FAELT,mask)
Returnerar positionen för det minsta elementet i fältet FAELT, eventuellt bara av de som uppfyller relationen i MASK. Resultatet kommer som en heltalsvektor!

I Fortran 95 tillkom att dessa funktionener kunde ha ytterligare ett frivilligt argument, dvs MAXLOC(FAELT,dim,mask) respektive MINLOC(FAELT,dim,mask).

A 5.20 Pekarförfrågansfunktioner

ASSOCIATED(POINTER,target)
Logisk funktion som talar om ifall pekaren POINTER är associerad med ett mål, om TARGET är med om den är associerad med just det målet. Om både POINTER och TARGET är pekare blir resultatet sant endast om båda är associerade med samma mål. Se i första hand kapitel 12, Pekare.

NULL() är en funktion introducerad i Fortran 95 för initial "nollställning" av pekare. Den användes på följande sätt på vektorn VEKTOR.

        REAL, POINTER, DIMENSION(:) :: VEKTOR => NULL()

Argumentet är inte nödvändigt, om det är närvarande bestämmer det egenskaperna hos pekaren, vilka annars bestämmes ur sammanhanget.

A 5.21 Inbyggda subrutiner

Det finns i Fortran 90 fem inbyggda subrutiner.

A 5.21.1 Tidsrutiner

Här finns de två rutinerna DATE_AND_TIME och SYSTEM_CLOCK samt den nya (från Fortran 95) CPU_TIME.
DATE_AND_TIME(date,time,zone,values)
Subrutin som ger datum, tid och tidszon. Minst ett argument måste ges.

DATE skall vara en skalär textsträngsvariabel med minst 8 tecken, och den tilldelas värdet CCYYMMDD för århundrade, år, månad och dag. Samtliga ges numeriskt, med blanka om systemet ej innehåller datum.

TIME skall vara en skalär textsträngsvariabel med minst 10 tecken, och den tilldelas värdet hhmmss.sss för timme, minut och sekunder. Samtliga ges numeriskt, med blanka om systemet ej innehåller klocka.

ZONE skall vara en skalär textsträngsvariabel med minst 5 tecken, och den tilldelas värdet +hhmm för tecken, timme och minut för den lokala tidsdifferensen mot UTC (före detta GMT). Samtliga ges numeriskt, med blanka om systemet ej innehåller klocka. Vi får således här i Sverige +0100 under vintern och +0200 under sommaren.

VALUES är i stället en heltalsvektor med minst 8 element, vilket gör det lättare att använda resultaten från DATE_TIME vid beräkningar i det egna programmet. Om systemet saknar datum respektive klocka erhålles -HUGE(0), dvs det minsta heltalet i modellen, som svar. Vektorn kommer att innehålla följande element: år, månad, dag, tidsdifferens i minuter, timme, minut, sekund och millisekunder.

SYSTEM_CLOCK(count,count_rate,count_max)
Subrutin som ger systemtiden. Minst ett argument måste ges.

COUNT är ett skalärt heltal som ger systemtiden, vilken uppräknas med 1 för varje cykel, upp till COUNT_MAX, då den börjar om. Om systemklocka saknas erhålles -HUGE(0).

COUNT_RATE är ett skalärt heltal som ger antalet cykler per sekund. Om systemklocka saknas erhålles 0.

COUNT_MAX är ett skalärt heltal som ger det maximala värde som COUNT kan nå. Om systemklocka saknas erhålles 0.

CPU_TIME(TIME)

Denna subrutin introducerades i Fortran 95. I den skalära flytpunktsvariabeln TIME erhålles processortiden i sekunder. För att få tiden för en viss uppgift måste en subtraktion utföras. Den exakta tidsbestämningen, speciellt för parallella processorer, är implementationsberoende.

A 5.21.2 Bitkopieringsrutin

MVBITS(FROM,FROMPOS,LEN,TO,TOPOS)
Subrutin som kopierar den följd av bitar i FROM som startar i position FROMPOS och har längden LEN till TO, med början i position TOPOS. Övriga bitar ändras ej. Alla storheter måste vara heltal, alla utom TO med INTENT(IN), medan TO skall ha INTENT(INOUT) och ha samma slag som FROM. Samma variabel kan vara både FROM och TO. Vissa naturliga restriktioner på tillåtna värden på LEN, FROMPOS och TOPOS gäller, även med hänsyn till BIT_SIZE.

A 5.21.3 Slumptalsrutiner

Här finns de två rutinerna RANDOM_NUMBER och RANDOM_SEED.

En följd av pseudoslumptal genereras från ett startvärde, som är lagrat som en heltalsvektor. Subrutinerna erbjuder ett flyttbart gränssnitt gentemot en implementationsberoende slumptalsföljd.

RANDOM_NUMBER(HARVEST)
Denna subrutin returnerar i flyttalsvariabeln HARVEST ett (eller flera om HARVEST är ett fält) slumptal mellan noll och ett.
RANDOM_SEED(size,put,get)
Denna subrutin omstartar eller ger information om slumptalsgeneratorn. Inget argument behöver vara med. Utvariabeln SIZE skall vara ett skalärt heltal och den ger antalet heltal (n) som processorn utnyttjar för startvärdet. Invariabeln PUT är en heltalsvektor som sätter startvärdet, medan utvariabeln GET avläser aktuellt startvärde. Exempel:
        CALL RANDOM_SEED                   Initiering
        CALL RANDOM_SEED (SIZE=K)          Sätter K = n 
        CALL RANDOM_SEED (PUT = SEED(1:K)) Använder användarens
                                             startvärden
        CALL RANDOM_SEED (GET = OLD(1:K))  Avläser aktuella
                                             startvärden
Ett enkelt exempel på användning av dessa rutiner finns nu.

Genomgång av hela språket Forttan 90 Innehåll NAG:s Fortran 90/95


Senast modifierad: 27 maj 2007
boein@nsc.liu.se