Jazykové funkce Fortran 95 - Fortran 95 language features

Toto je přehled Jazykové funkce Fortran 95. Zahrnuty jsou další funkce TR-15581: Enhanced Data Type Facilities, které byly univerzálně implementovány. Staré funkce, které byly nahrazeny novými, nejsou popsány - některé z těchto historických prvků se používají v moderních programech, ačkoli většina z nich byla zachována v jazyce, aby byla zachována zpětná kompatibilita. Současným standardem je Fortran 2018; mnoho z jeho nových funkcí je stále implementováno v kompilátorech.[1] Další funkce Fortran 2003, Fortran 2008 a Fortran 2018 jsou popsány Metcalfem, Reidem a Cohenem.[2]

Jazykové prvky

Fortran je velká a malá písmena. Konvence psaní Fortranových klíčových slov velkými písmeny a všech ostatních jmen malými písmeny je přijata v tomto článku; kromě toho, v kontrastu, v popisech vstupu / výstupu (Přenos dat a Operace s externími soubory ).

Základy

Základní složkou jazyka Fortran je jeho znaková sada. Jeho členy jsou

  • písmena A ... Z a a ... z (která jsou ekvivalentní mimo kontext znaků)
  • číslice 0 ... 9
  • podtržítko _
  • speciální znaky =: + prázdné - * / () [],. $ '! "% &; <>?

Žetony které mají syntaktický význam pro kompilátor, jsou vytvořeny z těchto komponent. Existuje šest tříd žetonů:

Označení123
Konstantní123,456789_long
Klíčové slovoPŘIDĚLITELNÉ
Operátor.přidat.
názevřešit_rovnici (až 31 znaků, včetně _)
Oddělovač / ( ) (/ /) [ ] , = => : :: ; %

Z tokenů prohlášení jsou postaveny. Ty lze kódovat pomocí nového bezplatného zdrojový formulář který nevyžaduje umístění v pevné konstrukci sloupu:

FUNKCE string_concat(s1, s2)                             ! Toto je komentář   TYP (tětiva), ÚMYSL(V) :: s1, s2   TYP (tětiva) string_concat   string_concat%string_data = s1%string_data(1:s1%délka) // &      s2%string_data(1:s2%délka)                          ! Toto je pokračování   string_concat%délka = s1%délka + s2%délkaKONEC FUNKCE string_concat

Všimněte si koncových komentářů a koncové značky pokračování. Může existovat 39 pokračovacích řádků a 132 znaků na řádek. Mezery jsou významné. Kde je tokenová nebo znaková konstanta rozdělena na dva řádky:

               ...        začátek&        &_název               ...   „velmi dlouhý a        &tětiva'

přední & na pokračující lince je také vyžadováno.

Automatický převod zdrojového formuláře pro stávající programy lze provést pomocí convert.f90.

Jeho možnosti jsou

  • významná manipulace s blanky;
  • odsazení;
  • POKRAČOVAT nahrazeno END DO;
  • název přidán do podprogramu END výkazu; a
  • Syntaxe INTEGER * 2 atd. Převedena.

Vnitřní datové typy

Fortran má pět vnitřní datové typy: CELÉ ČÍSLO, NEMOVITÝ, KOMPLEX, LOGICKÝ a CHARAKTER. Každý z těchto typů lze dále charakterizovat a druh. Druh v podstatě definuje interní reprezentaci typu: pro tři číselné typy definuje přesnost a rozsah a pro další dva specifika reprezentace úložiště. Jde tedy o abstraktní pojem, který modeluje limity zastoupení datových typů; je vyjádřen jako člen množiny celých čísel (např. může být {1, 2, 4, 8} pro celá čísla, označující bajty úložiště), ale tyto hodnoty nejsou specifikovány standardem a nejsou přenosné. Pro každý typ existuje výchozí druh, který se používá, pokud není výslovně uveden žádný druh. Pro každý vnitřní typ existuje odpovídající forma doslovná konstanta. Číselné typy CELÉ ČÍSLO a NEMOVITÝ lze pouze podepsat (pro typ neexistuje koncept znaménka KOMPLEX).

Doslovné konstanty a druhy

CELÉ ČÍSLO

Celočíselné konstanty literálu výchozího druhu mají podobu

1   0   -999   32767   +10

Druh lze definovat jako pojmenovanou konstantu. Pokud je požadovaný rozsah ± 10druh, přenosná syntaxe pro definování vhodného druhu, dva_byty je

CELÉ ČÍSLO, PARAMETR :: dva_byty = SELECTED_INT_KIND(4)

který umožňuje následnou definici konstant formuláře

-1234_two_bytes   +1_two_bytes

Tady, dva_byty je parametr typu druhu; může to být také explicitní výchozí celočíselná konstanta literálu, jako

-1234_2

ale takové použití je nepřenosné.

Funkce KIND dodává hodnotu parametru druhu druhu:

DRUH(1)            DRUH(1_two_bytes)

a ROZSAH funkce dodává skutečný desetinný rozsah (takže uživatel musí provést skutečné mapování na bajty):

ROZSAH(1_two_bytes)

Také v DATA (inicializační) příkazy, lze použít binární (B), osmičkové (O) a hexadecimální (Z) konstanty (často neformálně označované jako „BOZ konstanty“):

B'01010101'   Ó'01234567'   Z'10fa'
NEMOVITÝ

Existují alespoň dva skutečné druhy - výchozí a jeden s větší přesností (nahrazuje DVOJNÁSOBNÁ PŘESNOST). SELECTED_REAL_KIND funkce vrací číslo druhu pro požadovaný rozsah a přesnost; pro nejméně 9 desetinných míst přesnosti a rozsah 10−99 do 1099, lze jej zadat jako:

CELÉ ČÍSLO, PARAMETR :: dlouho = SELECTED_REAL_KIND(9, 99)

a literály následně specifikované jako

1.7_long

Existují také vnitřní funkce

DRUH(1.7_long)   PŘESNOST(1.7_long)   ROZSAH(1.7_long)

které zase dávají hodnotu druhu, skutečnou přesnost (zde minimálně 9) a skutečný rozsah (zde minimálně 99).

KOMPLEX

KOMPLEX datový typ je sestaven ze dvou celých nebo skutečných komponent:

(1, 3,7_dlouho)
LOGICKÝ

Existují pouze dvě základní hodnoty logických konstant: .SKUTEČNÝ. a .NEPRAVDIVÉ.. Tady mohou být také různé druhy. Logické společnosti nemají své vlastní druhy dotazovacích funkcí, ale používají druhy určené pro CELÉ ČÍSLOs; výchozí druh LOGICKÝ je stejný jako u INTEGER.

.NEPRAVDIVÉ.   .skutečný._one_byte

a DRUH funkce funguje podle očekávání:

DRUH(.SKUTEČNÝ.)
CHARAKTER

Formy doslovných konstant pro CHARAKTER datové typy jsou

'Řetězec'   "Další"   'Citát"'   '''''''

(poslední je prázdný řetězec). Jsou povoleny různé druhy (například rozlišovat ASCII a UNICODE strings), ale kompilátory jej příliš nepodporují. Opět platí, že druhová hodnota je dána DRUH funkce:

DRUH('ASCII')

Číselný model a vnitřní funkce

Číselné typy jsou založeny na číselných modelech s přidruženými dotazovacími funkcemi (jejichž hodnoty jsou nezávislé na hodnotách jejich argumentů; argumenty se používají pouze k poskytnutí druhu). Pro přenosný numerický software jsou důležité tyto funkce:

ČÍSLICE (X)Počet platných číslic
EPSILON (X)Téměř zanedbatelné ve srovnání s jedním (skutečné)
OBROVSKÉ (X)Největší číslo
MAXEXPONENT (X)Maximální exponent modelu (reálný)
MINEXPONENT (X)Minimální exponent modelu (skutečný)
PŘESNOST (X)Desetinná přesnost (skutečná, složitá)
RADIX (X)Základna modelu
ROZSAH (X)Rozsah desetinných exponentů
TINY (X)Nejmenší kladné číslo (skutečné)

Skalární proměnné

Skalární proměnné odpovídající pěti vnitřním typům jsou specifikovány následovně:

CELÉ ČÍSLO(DRUH=2) :: iNEMOVITÝ(DRUH=dlouho) :: AKOMPLEX         :: proudLOGICKÝ         :: PravdaCHARAKTER(LEN=20) :: slovoCHARAKTER(LEN=2, DRUH=Kanji) :: kanji_word

kde nepovinné DRUH parametr určuje jiný než výchozí druh a :: notation delimits the type and attributes from variable name (s) and their optional initial values, allowing full variable specification and initialization to be typed in one statement (in previous standards, attributes and initializers have to be declared in several statements). I když to výše uvedené příklady nevyžadují (protože neexistují žádné další atributy a inicializace), většina programátorů Fortran-90 si osvojuje zvyk používat je všude.

LEN= specifikátor je použitelný pouze pro CHARAKTERsa určuje délku řetězce (nahrazuje starší * len formulář). Explicitní DRUH = a LEN = specifikátory jsou volitelné:

CHARAKTER(2, Kanji) :: kanji_word

funguje stejně dobře.

Existují některé další zajímavé rysy postavy. Stejně jako podřetězec jako v

CHARAKTER(80) :: čára   ... = čára(i:i)                     ! podřetězec

bylo dříve možné, takže nyní je podřetězec

'0123456789'(i:i)

Jsou povoleny také řetězce nulové délky:

čára(i:i-1)       ! řetězec nulové délky

Nakonec je zde sada funkcí vnitřních znaků, příklady jsou

ACHARIACHAR (pro sadu ASCII)
NASTAVITNASTAVIT
LEN_TRIMINDEX (s1, s2, BACK = .TRUE.)
OPAKOVATSKENOVAT(pro jednu ze sady)
TRIMOVĚŘTE(pro celou sadu)

Odvozené datové typy

U odvozených datových typů musí být nejprve definována forma typu:

TYP osoba   CHARAKTER(10) název   NEMOVITÝ stáříKONEC TYPU osoba

a poté lze definovat proměnné tohoto typu:

TYP(osoba) vy, 

Chcete-li vybrat komponenty odvozeného typu, % používá se kvalifikátor:

vy%stáří

Doslovné konstanty odvozených typů mají formu TypeName (1stComponentLiteral, 2ndComponentLiteral, ...):

vy = osoba('Kovář', 23.5)

který je známý jako konstruktor struktury. Definice mohou odkazovat na dříve definovaný typ:

TYP směřovat   NEMOVITÝ X, yKONEC TYPU směřovatTYP trojúhelník   TYP(směřovat) A, b, CKONEC TYPU trojúhelník

a pro proměnnou typu trojúhelník, jako v

TYP(trojúhelník) t

každá složka typu směřovat je přístupný jako

t%A   t%b   t%C

které zase mají konečné komponenty typu real:

t%A%X   t%A%y   t%b%X   atd.

(Všimněte si, že % místo tečky byl vybrán kvalifikátor (.) kvůli možné nejednoznačnosti s notací operátora, jako .NEBO.).

Implicitní a explicitní psaní

Pokud není uvedeno jinak, jsou výchozí všechny proměnné začínající písmeny I, J, K, L, M a N. CELÉ ČÍSLOs a všechny ostatní jsou výchozí NEMOVITÝ; jiné datové typy musí být výslovně deklarovány. Toto je známé jako implicitní psaní a je dědictvím prvních dnů FORTRANU. Tato výchozí nastavení lze přepsat IMPLICIT TypeName (CharacterRange) prohlášení, jako:

IMPLICITNÍ KOMPLEX(Z)IMPLICITNÍ CHARAKTER(A-B)IMPLICITNÍ NEMOVITÝ(C-H,N-Y)

Je však dobrým zvykem explicitně psát všechny proměnné, což lze vynutit vložením příkazu IMPLICIT ŽÁDNÝna začátku každé programové jednotky.

Pole

Pole jsou považována za proměnné samy o sobě. Každé pole je charakterizováno svým typ, hodnost, a tvar (což definuje rozsahy každé dimenze). Hranice každé dimenze jsou ve výchozím nastavení 1 a velikost, ale je možné výslovně specifikovat libovolné hranice. DIMENZE klíčové slovo je volitelné a považuje se za atribut; pokud je vynechán, musí být tvar pole zadán za názvem proměnné pole. Například,

NEMOVITÝ:: A(10)CELÉ ČÍSLO, DIMENZE(0:100, -50:50) :: mapa

deklaruje dvě pole, pořadí 1 a pořadí 2, jejichž prvky jsou v sloupová hlavní objednávka. Prvky jsou například

A(1)  A(i*j)

a jsou skaláry. Dolní indexy mohou být jakýkoli skalární celočíselný výraz.

Sekce jsou součástí proměnných pole a jsou to samotná pole:

A(i:j)               ! první místomapa(i:j, k:l:m)      ! druhé místoA(mapa(i, k:l))       ! vektorový dolní indexA(3:2)               ! nulová délka

Celá pole a sekce pole jsou objekty s hodnotou pole. K dispozici jsou konstanty s hodnotou pole (konstruktory), uzavřené v (/ ... /):

(/ 1, 2, 3, 4 /)(/ ( (/ 1, 2, 3 /), i = 1, 4) /)(/ (i, i = 1, 9, 2) /)(/ (0, i = 1, 100) /)(/ (0.1*i, i = 1, 10) /)

s využitím implicitní notace smyčky DO. Fortran 2003 umožňuje použití závorek: [1, 2, 3, 4] a [([[1,2,3], i = 1,4)]místo prvních dvou výše uvedených příkladů to nyní podporuje mnoho překladačů. Odvozený datový typ může samozřejmě obsahovat komponenty pole:

TYP trojice   NEMOVITÝ, DIMENZE(3) :: vrcholKONEC TYPU trojiceTYP(trojice), DIMENZE(4) :: t

aby

  • t(2) je skalární (struktura)
  • t(2)%vrchol je složka pole skaláru

Inicializace dat

Proměnným lze dát počáteční hodnoty, jak je uvedeno ve specifikačním prohlášení:

NEMOVITÝ, DIMENZE(3) :: A = (/ 0.1, 0.2, 0.3 /)

a výchozí počáteční hodnota může být dána komponentě odvozeného datového typu:

TYP trojice   NEMOVITÝ, DIMENZE(3) :: vrchol = 0.0KONEC TYPU trojice

Když jsou lokální proměnné inicializovány v rámci procedury, implicitně získají atribut SAVE:

NEMOVITÝ, DIMENZE(3) :: směřovat = (/ 0.0, 1.0, -1.0 /)

Toto prohlášení je ekvivalentní s

NEMOVITÝ, DIMENZE(3), ULOŽIT :: směřovat = (/ 0.0, 1.0, -1.0 /)

pro lokální proměnné v podprogramu nebo funkci. Atribut SAVE způsobí, že si lokální proměnné po volání procedury zachovají svoji hodnotu a poté po návratu do procedury inicializují proměnnou na uloženou hodnotu.

Atribut PARAMETER

Pojmenovanou konstantu lze zadat přímo přidáním PARAMETR atribut a konstantní hodnoty příkazu typu:

NEMOVITÝ, DIMENZE(3), PARAMETR :: pole = (/ 0., 1., 2. /)TYP(trojice), PARAMETR :: t = trojice( (/ 0., 0., 0. /) )

Prohlášení DATA

The DATA příkaz lze použít pro skaláry a také pro pole a proměnné odvozeného typu. Je to také jediný způsob, jak inicializovat jen části takových objektů, stejně jako inicializovat na binární, osmičkové nebo hexadecimální hodnoty:

TYP(trojice) :: t1, t2DATA t1/trojice( (/ 0., 1., 2. /) )/, t2%vrchol(1)/123./DATA pole(1:64) / 64*0/DATA i, j, k/ B'01010101', Ó'77', Z'ff'/

Inicializační výrazy

Hodnoty použité v DATA a PARAMETR příkazy nebo s těmito atributy jsou konstantní výrazy, které mohou zahrnovat odkazy na: konstruktory polí a struktur, elementární vnitřní funkce s celočíselnými nebo znakovými argumenty a výsledky a šest transformačních funkcí REPEAT, SELECTED_INT_KIND, TRIM, SELECTED_REAL_KIND, RESHAPE a PŘEVOD (vidět Vnitřní postupy ):

CELÉ ČÍSLO, PARAMETR :: dlouho = SELECTED_REAL_KIND(12),   &                      pole(3) = (/ 1, 2, 3 /)

Specifikační výrazy

Je možné určit podrobnosti proměnných pomocí libovolného nekonstantního, skalárního, celočíselného výrazu, který může také zahrnovat odkazy na dotazovací funkce:

PODPROGRAM s(b, m, C)   POUŽITÍ mod                                 ! obsahuje a   NEMOVITÝ, DIMENZE(:, :)             :: b   NEMOVITÝ, DIMENZE(UBOUND(b, 1) + 5) :: X   CELÉ ČÍSLO                           :: m   CHARAKTER(LEN=*)                  :: C   CHARAKTER(LEN= m + LEN(C))        :: cc   NEMOVITÝ (SELECTED_REAL_KIND(2*PŘESNOST(A))) :: z

Výrazy a úkoly

Skalární numerická

K dispozici jsou obvyklé aritmetické operátory - +, -, *, /, ** (uvedeno zde v rostoucím pořadí).

V případě potřeby se k označení pořadí hodnocení používají závorky:

A*b + C     ! * za prvéA*(b + C)   ! + první

Pravidla pro skalární numerická výrazy a přiřazení se přizpůsobují nestandardním druhům. Číselný výraz a pravidla přiřazení smíšeného režimu tedy očekávaným způsobem začleňují různé parametry typu druhu:

skutečný2 = integer0 + skutečný1

převádí integer0 na skutečnou hodnotu stejného druhu jako skutečný1; výsledek je stejného druhu a je převeden na druh skutečný2 pro přiřazení.

Tyto funkce jsou k dispozici pro ovládání zaokrouhlování reálných čísel na celá čísla:

  • NINT: zaokrouhlit na nejbližší celé číslo, vrátit celočíselný výsledek
  • ANINT: zaokrouhlit na nejbližší celé číslo, vrátit skutečný výsledek
  • INT: zkrátit (zaokrouhlit na nulu), vrátit celočíselný výsledek
  • AINT: zkrátit (zaokrouhlit na nulu), vrátit skutečný výsledek
  • STROP: nejmenší integrální hodnota ne méně než argument (zaokrouhlit nahoru) (Fortran-90)
  • PODLAHA: největší integrální hodnota ne větší než argument (zaokrouhleno dolů) (Fortran-90)

Skalární relační operace

Pro skalární relační operace číselných typů, existuje sada integrovaných operátorů:

<<= == / =>> =. LT. .LE. .EQ. .NE. . GT. .GE.

(výše uvedené formuláře jsou pro Fortran-90 nové a pod nimi jsou uvedeny starší ekvivalentní formuláře). Příklad výrazů:

A < b .A. i /= j      ! pro číselné proměnnévlajka = A == b           ! pro příznaky logických proměnných

Skalární znaky

V případě skalární znaky a dané CHARAKTER(8) výsledek

je legální psát

výsledek(3:5) = výsledek(1:3)    ! překrytí je povolenovýsledek(3:3) = výsledek(3:2)    ! žádné přiřazení nulového řetězce

Zřetězení provádí operátor '//'.

výsledek = 'abcde'//'123'název souboru = výsledek//„.dat“

Odvozené datové typy

Mezi nimi neexistují žádné vestavěné operace (kromě přiřazení definovaného na základě jednotlivých komponent) odvozené datové typy vzájemně nebo s vnitřními typy. Význam existujících nebo uživatelem zadaných operátorů lze (znovu) definovat:

TYP řetězec80   CELÉ ČÍSLO délka   CHARAKTER(80) hodnotaKONEC TYPU řetězec80CHARAKTER::    char1, char2, char3TYP(řetězec80):: str1,  str2,  str3

můžeme psát

str3  = str1//str2       ! musí definovat operacistr3  = str1.concat.str2 ! musí definovat provozchar3 = char2//char3     ! pouze vnitřní operátorstr3  = char1            ! musí definovat přiřazení

Všimněte si „přetížený "použití vnitřního symbolu // a pojmenovaný operátor, .concat. . Rozdíl mezi těmito dvěma případy spočívá v tom, že pro token vnitřní operátor platí obvyklá pravidla priority, zatímco pro pojmenované operátory je priorita nejvyšší jako unární operátor nebo nejnižší jako binární. v

vektor3 = matice    *    vektor1  + vektor2vektor3 =(matice .krát. vektor1) + vektor2

dva výrazy jsou ekvivalentní, pouze pokud jsou přidány příslušné závorky, jak je znázorněno. V každém případě musí být definováno v a modul, procedury definující operátora a přiřazení a odpovídající asociace operátor-procedura, takto:

ROZHRANÍ OPERÁTOR(//) ! Přetíží operátor // jako vyvolání procedury string_concat  POSTUP MODULU string_concatKONEC ROZHRANÍ

Funkce zřetězení řetězců je propracovanější verzí verze, která je již uvedena v Základy. Všimněte si, že za účelem zpracování chybového stavu, který vzniká, když dva řetězce společně překročí přednastavený limit 80 znaků, by bylo bezpečnější použít podprogram k provedení zřetězení (v tomto případě by přetížení operátorem nebylo použitelné.)

MODUL řetězec_typ   IMPLICIT ŽÁDNÝ   TYP řetězec80      CELÉ ČÍSLO délka      CHARAKTER(LEN=80)   :: string_data   KONEC TYPU řetězec80   ROZHRANÍ ÚKOL(=)      POSTUP MODULU c_to_s_assign, s_to_c_assign   KONEC ROZHRANÍ   ROZHRANÍ OPERÁTOR(//)      POSTUP MODULU string_concat   KONEC ROZHRANÍOBSAHUJE   PODPROGRAM c_to_s_assign(s, C)      TYP (řetězec80), ÚMYSL(VEN)    :: s      CHARAKTER(LEN=*), ÚMYSL(V)  :: C      s%string_data = C      s%délka = LEN(C)   KONEC PODPROGRAMU c_to_s_assign   PODPROGRAM s_to_c_assign(C, s)      TYP (řetězec80), ÚMYSL(V)     :: s      CHARAKTER(LEN=*), ÚMYSL(VEN) :: C      C = s%string_data(1:s%délka)   KONEC PODPROGRAMU s_to_c_assign   TYP(řetězec80) FUNKCE string_concat(s1, s2)      TYP(řetězec80), ÚMYSL(V) :: s1, s2      TYP(řetězec80) :: s      CELÉ ČÍSLO :: n1, n2      CHARAKTER(160) :: ctot      n1 = LEN_TRIM(s1%string_data)      n2 = LEN_TRIM(s2%string_data)      LI (n1+n2 <= 80) paks%string_data = s1%string_data(1:n1)//s2%string_data(1:n2)      JINÝ  ! Toto je chybový stav, který by měl být zpracován - zatím pouze zkrácen         ctot = s1%string_data(1:n1)//s2%string_data(1:n2)         s%string_data = ctot(1:80)      END IFs%délka = LEN_TRIM(s%string_data)      string_concat = s   KONEC FUNKCE string_concatKONEC MODULU řetězec_typPROGRAM hlavní   POUŽITÍ řetězec_typ   TYP(řetězec80) :: s1, s2, s3   VOLÁNÍ c_to_s_assign(s1,'Jmenuji se')   VOLÁNÍ c_to_s_assign(s2,'Linus Torvalds')   s3 = s1//s2   PSÁT SI(*,*) 'Výsledek: ',s3%string_data   PSÁT SI(*,*) 'Délka:',s3%délkaKONEC PROGRAMU

Definované operátory, jako jsou tyto, jsou vyžadovány pro výrazy, které jsou povoleny také v konstruktorech struktury (viz Odvozené datové typy ):

str1 = tětiva(2, char1//char2)  ! konstruktor struktury

Pole

V případě polí se pak operace a přiřazení, pokud mají stejný tvar (přizpůsobitelné), rozšiřují zřejmým způsobem na základě jednotlivých prvků. Například daná prohlášení o

NEMOVITÝ, DIMENZE(10, 20) :: A, b, CNEMOVITÝ, DIMENZE(5)      :: proti, wLOGICKÝ vlajka(10, 20)

lze napsat:

A = b                                       ! přiřazení celého poleC = A/b                                     ! celé dělení a přiřazení poleC = 0.                                      ! celé pole přiřazení skalární hodnotyw = proti + 1.                                  ! přidání celého pole ke skalární hodnotěw = 5/proti + A(1:5, 5)                         ! rozdělení pole a přidání do sekcevlajka = A==b                                 ! celé pole relační test a přiřazeníC(1:8, 5:10) = A(2:9, 5:10) + b(1:8, 15:20) ! přidání a přiřazení sekce poleproti(2:5) = proti(1:4)                             ! přiřazení překrývající se sekce

Pořadí vyhodnocení výrazu není zadáno, aby bylo možné optimalizovat na paralelních a vektorových strojích. Samozřejmě musí být definovány všechny operátory pro pole odvozeného typu.

Některé skutečné vnitřní funkce, které jsou užitečné pro numerické výpočty, jsou

STROPNÍ PODLAHOVÁ MODULO (taky celé číslo)EXPONENTNÍ FRAKCENEJBLIŽŠÍ ROZMĚRY ROZDĚLENÍSCALE SET_EXPONENT

Jedná se o pole s hodnotou pro argumenty pole (elementární), stejně jako všechny FORTRAN 77 funkce (kromě LEN):

INT NEMOVITÝ CMPLXAINT ANINT NINTABS MOD SIGNDIM MAX MINSQRT EXP LOGLOG10           SIN COSTAN ASIN ACOSOPÁLENÍ ATAN2SINH COSH TANHAIMAG CONJGLGE LGT LLELLT ICHAR CHARINDEX

(posledních sedm je pro znaky).

Kontrolní prohlášení

Větvení a podmínky

Jednoduché JÍT DO označení existuje, ale obvykle se mu vyhýbá - ve většině případů bude konkrétnější větvicí konstrukt provádět stejnou logiku s větší jasností.

Jednoduchý podmíněný test je LI prohlášení: LI (A > b) X = y

Plnohodnotný LI konstrukt ilustruje

LI (i < 0) PAK   LI (j < 0) PAKX = 0.   JINÝz = 0.   END IFJINÉ IF (k < 0) PAKz = 1.JINÝX = 1.END IF

Konstrukce CASE

The PŘÍPAD konstrukt je náhradou za vypočítaný JÍT DO, ale je lépe strukturovaný a nevyžaduje použití štítků prohlášení:

VYBERTE PŘÍPAD (číslo)       ! číslo typu celé čísloPŘÍPAD (:-1)                 ! všechny hodnoty pod 0   n_sign = -1PŘÍPAD (0)                   ! pouze 0   n_sign = 0PŘÍPAD (1:)                  ! všechny hodnoty nad 0   n_sign = 1KONEC VÝBĚRU

Každý PŘÍPAD seznam selektorů může obsahovat seznam a / nebo rozsah celých čísel, znaků nebo logických konstant, jejichž hodnoty se nesmí překrývat uvnitř selektorů nebo mezi nimi:

PŘÍPAD (1, 2, 7, 10:17, 23)

K dispozici je výchozí nastavení:

PŘÍPAD VÝCHOZÍ

Existuje pouze jedno hodnocení a pouze jedna shoda.

DO konstrukce

Zjednodušená, ale dostatečná forma DĚLAT konstrukt ilustruje

vnější: DĚLATvnitřní:    DĚLAT i = j, k, l      ! od j do k v krocích po l (l je volitelné)             :             LI (...) CYKLUS             :             LI (...) VÝSTUP vnější             :          KONEC DO vnitřní       KONEC DO vnější

kde si všimneme, že smyčky mohou být volitelně pojmenovány, takže jakýkoli příkaz EXIT nebo CYCLE může určit, která smyčka je míněna.

Mnoho jednoduchých smyček, ale ne všechny, lze nahradit výrazy a přiřazeními pole nebo novými vnitřními funkcemi. Například

tot = 0.DĚLAT i = m, n   tot = tot + A(i)KONEC DO

se stává jednoduše tot = SOUČET( A(m:n) )

Programové jednotky a postupy

Definice

Abychom mohli diskutovat o tomto tématu, potřebujeme několik definic. Logicky řečeno, spustitelný program se skládá z jednoho hlavní program a nula nebo více podprogramy (nebo postupy) - něco dělají. Podprogramy jsou buď funkce nebo podprogramy, které jsou buď vnější, vnitřní nebo modul podprogramy. (Externí podprogramy jsou to, co jsme znali z FORTRANU 77.)

Z organizačního hlediska však kompletní program sestává z programové jednotky. To jsou buď hlavní programy, externí podprogramy nebo moduly a lze je sestavit samostatně.

Příkladem hlavního (a úplného) programu je

PROGRAM test   TISK *, 'Ahoj světe!'KONEC PROGRAMU test

Příkladem hlavního programu a externího podprogramu tvořícího spustitelný program je

PROGRAM test   VOLÁNÍ print_messageKONEC PROGRAMU testPODPROGRAM print_message   TISK *, 'Ahoj světe!'KONEC PODPROGRAMU print_message

Forma funkce je

FUNKCE název(arg1, arg2) ! nula nebo více argumentů   :                        název = ...   :KONEC FUNKCE název

Forma odkazu na funkci je X = název(A, b)

Interní postupy

Interní podprogram je jeden obsažené v jiném (na maximálně jedné úrovni vnoření) a poskytuje náhradu za funkci příkazu:

PODPROGRAM vnější   NEMOVITÝ X, y   :OBSAHUJE   PODPROGRAM vnitřní      NEMOVITÝ y      y = X + 1.      :   KONEC PODPROGRAMU vnitřní     ! PODPROGRAM povinnýKONEC PODPROGRAMU vnější

Říkáme to vnější je hostitel z vnitřní, a to vnitřní získá přístup k entitám v vnější podle hostitelská asociace (např X), zatímco y je místní proměnná na vnitřní.

The rozsah pojmenované entity je a zaměřovací jednotka, tady vnější méně vnitřní, a vnitřní.

Názvy programových jednotek a externích postupů jsou globálnía názvy implikovaných proměnných DO mají rozsah příkazu, který je obsahuje.

Moduly

Moduly se používají k balení

  • globální data (nahrazuje SPOLEČNÁ a BLOKOVÁNÍ ÚDAJŮ z Fortranu 77);
  • definice typu (samy o sobě rozsahovací jednotka);
  • podprogramy (které mimo jiné nahrazují použití VSTUPU z Fortranu 77);
  • bloky rozhraní (další zaměřovací jednotka, viz Bloky rozhraní );
  • skupiny jmenných seznamů (viz jakákoli učebnice).

Příkladem modulu obsahujícího definici typu, blok rozhraní a podprogram funkce je

MODUL interval_arithmetic   TYP interval      NEMOVITÝ dolní, horní   KONEC TYPU interval   ROZHRANÍ OPERÁTOR(+)       POSTUP MODULU add_intervals   KONEC ROZHRANÍ   :OBSAHUJE   FUNKCE add_intervals(A,b)      TYP(interval), ÚMYSL(V) :: A, b      TYP(interval) add_intervals      add_intervals%dolní = A%dolní + b%dolní      add_intervals%horní = A%horní + b%horní   KONEC FUNKCE add_intervals             ! FUNKCE povinná   :KONEC MODULU interval_arithmetic

a jednoduché prohlášení

     POUŽITÍ interval_arithmetic

poskytuje použít asociaci všem entitám modulu. Podprogramy modulů mohou zase obsahovat interní podprogramy.

Řízení přístupnosti

The VEŘEJNOST a SOUKROMÉ atributy se používají ve specifikacích v modulech k omezení rozsahu entit. Formulář atributu je

NEMOVITÝ, VEŘEJNOST     :: X, y, z           ! výchozíCELÉ ČÍSLO, SOUKROMÉ :: u, proti, w

a formulář prohlášení je

VEŘEJNOST  :: X, y, z, OPERÁTOR(.přidat.)SOUKROMÉ :: u, proti, w, ÚKOL(=), OPERÁTOR(*)

Formulář prohlášení je třeba použít k omezení přístupu k operátorům a lze jej také použít ke změně celkového výchozího nastavení:

SOUKROMÉ                        ! nastaví výchozí pro modulVEŘEJNOST  :: pouze toto

U odvozených typů existují tři možnosti: typ a jeho komponenty jsou všechny VEŘEJNÉ, typ je VEŘEJNÝ a jeho komponenty SOUKROMÉ (pouze typ je viditelný a lze snadno změnit jeho podrobnosti), nebo všechny jsou SOUKROMÉ (pro interní použití) pouze v modulu):

MODUL těžit   SOUKROMÉ   TYP, VEŘEJNOST :: seznam      NEMOVITÝ X, y      TYP(seznam), UKAZATEL :: další   KONEC TYPU seznam   TYP(seznam) :: strom   :KONEC MODULU těžit

The POUŽITÍ účelem prohlášení je získat přístup k entitám v modulu. Má možnosti, jak vyřešit střety jmen, pokud je importovaný název stejný jako místní:

POUŽITÍ těžit, local_list => seznam

nebo omezit použité entity na zadanou sadu:

POUŽITÍ těžit, POUZE : seznam

Mohou být kombinovány:

POUŽITÍ těžit, POUZE : local_list => seznam

Argumenty

Můžeme určit záměr fiktivních argumentů:

PODPROGRAM zamíchat (karty, karty)  CELÉ ČÍSLO, ÚMYSL(V)  :: karty  CELÉ ČÍSLO, ÚMYSL(VEN), DIMENZE(karty) :: karty

Možný je také INOUT: zde musí být skutečný argument proměnná (na rozdíl od výchozího případu, kdy může být konstantní).

Argumenty mohou být volitelné:

PODPROGRAM mincon(n, F, X, horní, dolní, rovnosti, nerovnosti, konvexní, xstart)   NEMOVITÝ, VOLITELNÝ, DIMENZE :: horní, dolní   :   LI (SOUČASNOST, DÁREK(dolní)) PAK   ! test na přítomnost skutečného argumentu   :

umožňuje nám zavolat mincon podle

VOLÁNÍ mincon (n, F, X, horní)

Argumenty mohou být spíše klíčové než poziční (které jsou na prvním místě):

VOLÁNÍ mincon(n, F, X, rovnosti=0, xstart=x0)

Volitelné argumenty a argumenty klíčových slov jsou zpracovávány explicitními rozhraními, tj. S interními nebo modulovými procedurami nebo s bloky rozhraní.

Bloky rozhraní

Jakýkoli odkaz na interní nebo modulový podprogram je prostřednictvím rozhraní, které je „explicitní“ (tj. Kompilátor vidí všechny podrobnosti). Odkaz na externí (nebo fiktivní) proceduru je obvykle „implicitní“ (kompilátor předpokládá podrobnosti). I v tomto případě však můžeme poskytnout explicitní rozhraní. Jedná se o kopii záhlaví, specifikací a prohlášení KONEC příslušného postupu, buď umístěných v modulu, nebo vložených přímo:

NEMOVITÝ FUNKCE minimální(A, b, func)  ! vrací minimální hodnotu funkce func (x)  ! v intervalu (a, b)  NEMOVITÝ, ÚMYSL(v) :: A, b  ROZHRANÍNEMOVITÝ FUNKCE func(X)      NEMOVITÝ, ÚMYSL(V) :: X    KONEC FUNKCE func  KONEC ROZHRANÍNEMOVITÝ F,X  :  F = func(X)   ! vyvolání funkce uživatele.  :KONEC FUNKCE minimální

Explicitní rozhraní je povinné pro

  • argumenty volitelné a klíčové slovo;
  • Argumenty POINTER a TARGET (viz Ukazatele );
  • Výsledek funkce POINTER;
  • argumenty nového pole a funkce pole (Zpracování polí ).

Umožňuje úplné kontroly v době kompilace mezi skutečnými a fiktivními argumenty.

Nejlepší způsob, jak zajistit, aby bylo rozhraní procedury explicitní, je obecně umístit dotyčný postup do modulu nebo jej použít jako interní proceduru.

Přetížení a obecná rozhraní

Bloky rozhraní poskytují mechanismus, pomocí kterého jsme schopni definovat obecná jména pro konkrétní postupy:

ROZHRANÍ gama                   ! druhové jméno   FUNKCE sgamma(X)              ! konkrétní název      NEMOVITÝ (SELECTED_REAL_KIND( 6)) sgamma, X   KONEC   FUNKCE dgamma(X)              ! konkrétní název      NEMOVITÝ (SELECTED_REAL_KIND(12)) dgamma, X   KONECKONEC ROZHRANÍ

kde daná sada konkrétních jmen odpovídající obecnému jménu musí mít všechny funkce nebo všechny podprogramy. Pokud je toto rozhraní v modulu, pak je to jednoduše

ROZHRANÍ gamaPOSTUP MODULU sgamma, dgammaKONEC ROZHRANÍ

Můžeme použít existující jména, např. SIN a kompilátor třídí správné přidružení.

Už jsme viděli použití bloků rozhraní pro definované operátory a přiřazení (viz Moduly ).

Rekurze

Nepřímá rekurze je užitečná pro vícerozměrnou integraci. Pro

objem = integrovat(fy, ybounds)

Možná máme

REKURZIVNÍ FUNKCE integrovat(F, meze)   ! Integrujte f (x) z hranic (1) do hranic (2)   NEMOVITÝ integrovat   ROZHRANÍ      FUNKCE F(X)         NEMOVITÝ F, X      KONEC FUNKCE F   KONEC ROZHRANÍNEMOVITÝ, DIMENZE(2), ÚMYSL(V) :: meze   :KONEC FUNKCE integrovat

a integrovat se f (x, y) přes obdélník:

FUNKCE fy(y)   POUŽITÍ func           ! funkce modulu obsahuje funkci f   NEMOVITÝ fy, y   yval = y   fy = integrovat(F, xbounds)KONEC

Přímá rekurze je, když se procedura volá sama, jako v

REKURZIVNÍ FUNKCE faktoriál(n) VÝSLEDEK(res)   CELÉ ČÍSLO res, n   LI(n.EQ.0) PAKres = 1   JINÝres = n*faktoriál(n-1)   END IFKONEC

Zde si povšimneme VÝSLEDEK klauzule a test ukončení.

Čisté postupy

Toto je funkce pro paralelní výpočty.

v prohlášení a konstrukce FORALL, jakékoli vedlejší účinky ve funkci mohou bránit optimalizaci na paralelním procesoru - pořadí provádění přiřazení může ovlivnit výsledky. Pro kontrolu této situace přidáme ČISTÝ klíčové slovo do PODPROGRAM nebo FUNKCE prohlášení - tvrzení, že postup (vyjádřeno jednoduše):

  • nemění žádnou globální proměnnou,
  • neprovádí žádné I / O,
  • nemá žádné uložené proměnné (proměnné s ULOŽIT atribut, který si zachovává hodnoty mezi vyvoláními) a
  • pro funkce nemění žádný ze svých argumentů.

Kompilátor může zkontrolovat, že tomu tak je, jako v

ČISTÁ FUNKCE vypočítat (X)

Všechny vnitřní funkce jsou čisté.

Zpracování polí

Zpracování polí je ve Fortranu zahrnuto ze dvou hlavních důvodů:

  • notační pohodlí, které poskytuje, přibližuje kód základní matematické formě;
  • pro další optimalizační příležitosti, které dává překladačům (i když existuje spousta příležitostí i pro degradující optimalizaci!).

Současně byla přidána hlavní rozšíření funkcí v této oblasti. Už jsme potkali celá pole výše # Pole 1 a tady # Pole 2 - nyní vyvíjíme téma.

Pole nulové velikosti

S nulovou velikostí zachází Fortran jako s legitimním objektem, bez speciálního kódování programátorem. Tak, v

DĚLAT i = 1,n   X(i) = b(i) / A(i, i)   b(i+1:n) = b(i+1:n) - A(i+1:n, i) * X(i)KONEC DO

pro finální iteraci není vyžadován žádný speciální kód i = n. Poznamenáváme, že pole s nulovou velikostí je považováno za definované; pole tvaru (0,2) však není kompatibilní s polem tvaru (0,3), zatímco X(1:0) = 3 je platné prohlášení „nedělat nic“.

Pole předpokládaného tvaru

Jedná se o rozšíření a náhradu za pole předpokládané velikosti. Vzhledem k aktuální argument jako:

NEMOVITÝ, DIMENZE(0:10, 0:20) :: A   :VOLÁNÍ sub(A)

odpovídající specifikace fiktivního argumentu definuje pouze typ a pořadí pole, nikoli jeho tvar. Tyto informace musí být zpřístupněny explicitním rozhraním, často pomocí bloku rozhraní (viz Bloky rozhraní ). Píšeme tedy jen

PODPROGRAM sub(da)   NEMOVITÝ, DIMENZE(:, :) :: da

a to je, jako by da byly dimenzovány (11,21). Můžeme však určit libovolnou dolní mez a odpovídajícím způsobem mapovat pole.

NEMOVITÝ, DIMENZE(0:, 0:) :: da

Předává se tvar, nikoli hranice, kde výchozí dolní mez je 1 a výchozí horní mez je odpovídající rozsah.

Automatická pole

Částečná náhrada za použití, ke kterým ROVNOCENNOST bylo vloženo je poskytováno tímto zařízením, užitečné pro místní, dočasná pole, jako v

PODPROGRAM vyměnit(A, b)   NEMOVITÝ, DIMENZE(:)       :: A, b   NEMOVITÝ, DIMENZE(VELIKOST(A)) :: práce   práce = A   A = b   b = práceKONEC PODPROGRAMU vyměnit

Skutečné úložiště je obvykle udržováno na zásobníku.

ALLOCATABLE a ALLOCATE

Fortran poskytuje dynamické přidělování úložiště; spoléhá se na mechanismus ukládání haldy (a nahrazuje jiné použití ROVNOCENNOST). Příkladem pro vytvoření pracovního pole pro celý program je

MODUL work_array   CELÉ ČÍSLO n   NEMOVITÝ, DIMENZE(:,:,:), PŘIDĚLITELNÉ :: práceKONEC MODULUPROGRAM hlavní   POUŽITÍ work_array   ČÍST (vstup, *) n   PŘIDĚLIT(práce(n, 2*n, 3*n), STAT=postavení)   :   ROZDĚLIT (práce)

Pracovní pole lze šířit celým programem pomocí a POUŽITÍ příkaz v každé programové jednotce. Můžeme určit explicitní dolní mez a přidělit několik entit v jednom příkazu. Abychom uvolnili mrtvé úložiště, napíšeme například

ROZDĚLIT(A, b)

Přidělení polí je automatické, když vyjdou z rozsahu.

Elementární operace, úkoly a postupy

Již jsme se setkali s přiřazením a operacemi celého pole:

NEMOVITÝ, DIMENZE(10) :: A, bA = 0.          ! skalární vysílání; elementární přiřazeníb = SQRT(A)     ! výsledek vnitřní funkce jako objekt pole

Ve druhém přiřazení vnitřní funkce vrátí výsledek s hodnotou pole pro argument s hodnotou pole. Můžeme psát funkce s hodnotou pole sami (vyžadují explicitní rozhraní):

PROGRAM test   NEMOVITÝ, DIMENZE(3) :: A = (/ 1., 2., 3./),       &                         b = (/ 2., 2., 2. /),  r   r = F(A, b)   TISK *, rOBSAHUJE   FUNKCE F(C, d)   NEMOVITÝ, DIMENZE(:) :: C, d   NEMOVITÝ, DIMENZE(VELIKOST(C)) :: F   F = C*d        ! (nebo nějaká užitečnější funkce c a d)   KONEC FUNKCE FKONEC PROGRAMU test

Elementární procedury jsou specifikovány pomocí skalárních fiktivních argumentů, které lze volat pomocí skutečných argumentů pole. V případě funkce je tvar výsledku tvar argumentů pole.

Většina vnitřních funkcí je elementálních a Fortran 95 rozšiřuje tuto funkci na neintinické procedury, čímž poskytuje efekt zápisu ve Fortranu 90, 22 různých verzích, pro pozice 0-0, 0-1, 1-0, 1-1, 0- 2,2-0, 2-2, ... 7-7 a je další pomůckou pro optimalizaci na paralelních procesorech. Elementární postup musí být čistý.

PRVKOVÝ SUBROUTIN vyměnit(A, b)   NEMOVITÝ, ÚMYSL(DOVNITŘ VEN)  :: A, b   NEMOVITÝ                 :: práce   práce = A   A = b   b = práceKONEC PODPROGRAMU vyměnit

Fiktivní argumenty nelze použít ve specifikačních výrazech (viz výše ) kromě argumentů určitých vnitřních funkcí (BIT_SIZE, DRUH, LENa číselné dotazy, (viz níže ).

KDE

Často musíme úkol maskovat. To můžeme udělat pomocí KDE, buď jako prohlášení:

KDE (A /= 0.0) A = 1.0/A  ! vyhněte se dělení 0

(poznámka: test je element po elementu, ne na celém poli), nebo jako konstrukce:

KDE (A /= 0.0)   A = 1.0/A   b = A             ! všechna pole mají stejný tvarKONEC KDE

nebo

KDE (A /= 0.0)   A = 1.0/ANĚKDE JINDE   A = OBROVSKÝ(A)KONEC KDE

Dále:

  • je povoleno maskovat nejen KDE prohlášení KDE konstrukt, ale také jakýkoli NĚKDE JINDE prohlášení, které obsahuje;
  • A KDE konstrukce může obsahovat libovolný počet maskovaných NĚKDE JINDE prohlášení, ale nanejvýš jedno NĚKDE JINDE prohlášení bez masky, a to musí být poslední;
  • KDE konstrukty mohou být vnořeny do sebe, jen PRO VŠECHNY konstrukty;
  • A KDE přiřazovací příkaz může být definovaným přiřazením za předpokladu, že je elementární;
  • A KDE konstrukt může být pojmenován stejným způsobem jako jiné konstrukty.

Příkaz a konstrukce FORALL

Když DĚLAT konstrukce je provedena, každá následná iterace je prováděna v pořadí a jedna po druhé - překážka optimalizace na paralelním procesoru.

PRO VŠECHNY(i = 1:n) A(i, i) = X(i)

kde lze jednotlivé úkoly provádět v jakémkoli pořadí a dokonce i současně. The PRO VŠECHNY lze považovat za přiřazení pole vyjádřené pomocí indexů.

PRO VŠECHNY(i=1:n, j=1:n, y(i,j)/=0.) X(j,i) = 1.0/y(i,j)

se stavem maskování.

The PRO VŠECHNY konstrukce umožňuje provést několik příkazů přiřazení v pořadí.

A(2:n-1,2:n-1) = A(2:n-1,1:n-2) + A(2:n-1,3:n) + A(1:n-2,2:n-1) + A(3:n,2:n-1)b(2:n-1,2:n-1) = A(2:n-1,2:n-1)

je ekvivalentní přiřazení pole

PRO VŠECHNY(i = 2:n-1, j = 2:n-1)   A(i,j) = A(i,j-1) + A(i,j+1) + A(i-1,j) + A(i+1,j)   b(i,j) = A(i,j)KONEC FORALL

The PRO VŠECHNY verze je čitelnější.

Přiřazení v a PRO VŠECHNY je jako přiřazení pole: jako kdyby byly všechny výrazy vyhodnoceny v libovolném pořadí, uchovávány v dočasném úložišti, pak byla všechna přiřazení provedena v libovolném pořadí. První příkaz musí být úplně dokončen, než může začít druhý.

A PRO VŠECHNY mohou být vnořeny a mohou zahrnovat a KDEPostupy uvedené v rámci a PRO VŠECHNY musí být čistý.

Pole prvky

Pro jednoduchý případ

NEMOVITÝ, DIMENZE(100, 100) :: A

můžeme odkazovat na jeden prvek jako například a (1, 1). Pro odvozený datový typ jako

TYP fun_del   NEMOVITÝ u   NEMOVITÝ, DIMENZE(3) :: duKONEC TYPU fun_del

můžeme deklarovat pole tohoto typu:

TYP(fun_del), DIMENZE(10, 20) :: dehet

a odkaz jako dehet(n, 2) je prvek (skalární!) typu fun_del, ale dehet(n, 2)%du je pole typu real, a dehet(n, 2)%du(2) je jeho součástí. Základní pravidlo, které si musíte pamatovat, je, že prvek pole má vždy dolní index nebo dolní indexy kvalifikující alespoň příjmení.

Pole podobjektů (sekce)

Obecná forma dolního indexu pro část pole je

      [dolní] : [horní] [:krok]

(kde [] označuje volitelnou položku) jako v

NEMOVITÝ A(10, 10)A(i, 1:n)                ! část jednoho řádkuA(1:m, j)                ! část jednoho sloupceA(i, : )                 ! celý řádekA(i, 1:n:3)              ! každý třetí prvek řádkuA(i, 10:1:-1)            ! řádek v opačném pořadíA( (/ 1, 7, 3, 2 /), 1)  ! vektorový dolní indexA(1, 2:11:2)             ! 11 je legální, protože není uvedenA(:, 1:7)                ! sekce dvě

Všimněte si, že vektorový dolní index s duplicitními hodnotami se nemůže objevit na levé straně přiřazení, protože by byl nejednoznačný. Tím pádem,

b( (/ 1, 7, 3, 7 /) ) = (/ 1, 2, 3, 4 /)

je nezákonné. Část s vektorovým dolním indexem také nesmí být dodána jako skutečný argument pro VEN nebo DOVNITŘ VEN fiktivní argument. Pole polí nejsou povolena:

dehet%du             ! ilegální

Poznamenáváme, že na danou hodnotu v poli lze odkazovat jak na prvek, tak jako na sekci:

A(1, 1)            ! skalární (hodnocení nula)A(1:1, 1)          ! sekce pole (první místo)

v závislosti na okolnostech nebo požadavcích. Kvalifikací objektů odvozeného typu získáme prvky nebo sekce v závislosti na pravidle uvedeném dříve:

dehet%u              ! sekce pole (komponenta struktury)dehet(1, 1)%u        ! součást prvku pole

Pole vnitřních funkcí

Vektor a matice se množí

     DOT_PRODUCT Dotový produkt 2 řadových matic MATMUL Matrix multiplication

Redukce pole

     ALL True, pokud jsou všechny hodnoty pravdivé JAKÉKOLI True, pokud je některá hodnota pravdivá. Example:                            IF (ANY( a > b)) THEN     COUNT              Number of true elements in array     MAXVAL             Maximum value in an array     MINVAL             Minimum value in an array     PRODUCT            Product of array elements     SUM                Sum of array elements

Array inquiry

     ALLOCATED          Array allocation status     LBOUND             Lower dimension bounds of an array     SHAPE              Shape of an array (or scalar)     SIZE               Total number of elements in an array     UBOUND             Upper dimension bounds of an array

Array construction

     MERGE              Merge under mask     PACK               Pack an array into an array of rank one under a mask     SPREAD             Replicate array by adding a dimension     UNPACK             Unpack an array of rank one into an array under mask

Array reshape

     RESHAPE            Reshape an array

Array manipulation

     CSHIFT             Circular shift     EOSHIFT            End-off shift     TRANSPOSE          Transpose of an array of rank two

Array location

     MAXLOC             Location of first maximum value in an array     MINLOC             Location of first minimum value in an array

Ukazatele

Základy

Pointers are variables with the POINTER attribute; they are not a distinct data type (and so no 'pointer arithmetic' is possible).

NEMOVITÝ, POINTER :: var

They are conceptually a descriptor listing the attributes of the objects (targets) that the pointer may point to, and the address, if any, of a target. They have no associated storage until it is allocated or otherwise associated (by pointer assignment, see níže ):

ALLOCATE (var)

and they are dereferenced automatically, so no special symbol required. v

var = var + 2.3

the value of the target of var is used and modified. Pointers cannot be transferred via I/O. Prohlášení

PSÁT SI *, var

writes the value of the target of var and not the pointer descriptor itself.

A pointer can point to another pointer, and hence to its target, or to a static object that has the CÍLOVÁ attribute:

NEMOVITÝ, POINTER :: objektNEMOVITÝ, CÍLOVÁ  :: target_objvar => objekt                  ! pointer assignmentvar => target_obj

but they are strongly typed:

CELÉ ČÍSLO, POINTER :: int_varvar => int_var                 ! illegal - types must match

and, similarly, for arrays the ranks as well as the type must agree.

A pointer can be a component of a derived type:

TYPE entry                       ! type for sparse matrix   NEMOVITÝ hodnotaCELÉ ČÍSLO indexTYP(vstup), POINTER :: další  ! note recursionEND TYPE entry

and we can define the beginning of a linked chain of such entries:

TYP(vstup), POINTER :: řetěz

After suitable allocations and definitions, the first two entries could be addressed as

řetěz%hodnota řetěz%další%hodnotařetěz%index řetěz%další%indexřetěz%další            řetěz%další%další

but we would normally define additional pointers to point at, for instance, the first and current entries in the list.

Sdružení

A pointer's association status is one of

  • undefined (initial state);
  • associated (after allocation or a pointer assignment);
  • disassociated:
    DEALLOCATE (str, q)  ! for returning storageNULLIFY (str, q)     ! for setting to 'null'

Some care has to be taken not to leave a pointer 'dangling' by use of DEALLOCATE on its target without nullifying any other pointer referring to it.

The intrinsic function SOUVISEJÍCÍ can test the association status of a defined pointer:

LI (SOUVISEJÍCÍ(ukazatel)) THEN

or between a defined pointer and a defined target (which may, itself, be a pointer):

LI (SOUVISEJÍCÍ(ukazatel, cílová)) THEN

An alternative way to initialize a pointer, also in a specification statement,is to use the NULA funkce:

NEMOVITÝ, POINTER, DIMENZE(:) :: vektor => NULA() ! čas kompilacevektor => NULA()                                ! doba běhu

Pointers in expressions and assignments

For intrinsic types we can 'sweep' pointers over different sets of target data using the same code without any data movement. Given the matrix manipulation y = B C z, we can write the following code (although, in this case, the same result could be achieved more simply by other means):

NEMOVITÝ, CÍLOVÁ  :: b(10,10), C(10,10), r(10), s(10), z(10)NEMOVITÝ, POINTER :: A(:,:), X(:), y(:)CELÉ ČÍSLO mult:DĚLAT mult = 1, 2   LI (mult == 1) THENy => r              ! no data movement      A => C      X => z   ELSEy => s              ! no data movement      A => b      X => r   END IFy = MATMUL(A, X)       ! common calculationEND DO

For objects of derived type we have to distinguish between pointer and normal assignment. v

TYP(vstup), POINTER :: za prvé, proud:za prvé => proud

the assignment causes first to point at current, whereas

za prvé =  proud

causes current to overwrite first and is equivalent to

za prvé%hodnota = proud%hodnotaza prvé%index = proud%indexza prvé%další => proud%další

Pointer arguments

If an actual argument is a pointer then, if the dummy argument is also a pointer,

  • it must have same rank,
  • it receives its association status from the actual argument,
  • it returns its final association status to the actual argument (note: the target may be undefined!),
  • it may not have the ÚMYSL attribute (it would be ambiguous),
  • it requires an interface block.

If the dummy argument is not a pointer, it becomes associated with the target of the actual argument:

   NEMOVITÝ, POINTER :: A (:,:)      :   ALLOCATE (A(80, 80))      :   VOLÁNÍ sub(A)      :SUBROUTINE sub(C)   NEMOVITÝ C(:, :)

Pointer functions

Function results may also have the POINTER attribute; this is useful if the result size depends on calculations performed in the function, as in

POUŽITÍ data_handlerNEMOVITÝ X(100)NEMOVITÝ, POINTER :: y(:):y => kompaktní(X)

where the module data_handler contains

FUNKCE kompaktní(X)   NEMOVITÝ, POINTER :: kompaktní(:)   NEMOVITÝ X(:)   ! A procedure to remove duplicates from the array x   CELÉ ČÍSLO n   :              ! Find the number of distinct values, n   ALLOCATE(kompaktní(n))   :              ! Copy the distinct values into compactEND FUNCTION kompaktní

The result can be used in an expression (but must be associated with a defined target).

Arrays of pointers

These do not exist as such: given

TYP(vstup) :: řádky(n)

pak

řádky%další              ! ilegální

would be such an object, but with an irregular storage pattern. For this reason they are not allowed. However, we can achieve the same effect by defining a derived data type with a pointer as its sole component:

TYP řádek   NEMOVITÝ, POINTER :: r(:)END TYPE

and then defining arrays of this data type

TYP(řádek) :: s(n), t(n)

where the storage for the rows can be allocated by, for instance,

DĚLAT i = 1, n   ALLOCATE (t(i)%r(1:i)) ! Allocate row i of length iEND DO

The array assignment s = tis then equivalent to the pointer assignments s(i)%r => t(i)%r for all components.

Pointers as dynamic aliases

Vzhledem k řadě

NEMOVITÝ, CÍLOVÁ :: stůl(100,100)

that is frequently referenced with the fixed subscripts

stůl(m:n, str:q)

these references may be replaced by

NEMOVITÝ, DIMENZE(:, :), POINTER :: okno   :okno => stůl(m:n, str:q)

The subscripts of window are 1:n-m+1, 1:q-str+1. Podobně pro dehet%u(as defined in již ), we can use, say, taru => dehet%u to point at all the u components of tar, and subscript it as taru(1, 2)

The subscripts are as those of tar itself. (This replaces yet more of EQUIVALENCE.)

In the pointer association

ukazatel => array_expression

the lower bounds for ukazatel are determined as if lbound was applied to array_expression. Thus, when a pointer is assigned to a whole array variable, it inherits the lower bounds of the variable, otherwise, the lower bounds default to 1.

Fortran 2003 allows specifying arbitrary lower bounds on pointer association, like

okno(r:,s:) => stůl(m:n,str:q)

so that the bounds of okno stát se r:r+n-m,s:s+q-p.Fortran 95 does not have this feature; however, it can be simulated using thefollowing trick (based on the pointer association rules for assumed shape array dummy arguments):

FUNKCE remap_bounds2(lb1,lb2,pole) VÝSLEDEK(ptr)   CELÉ ČÍSLO, ÚMYSL(V)                            :: lb1,lb2   NEMOVITÝ, DIMENZE(lb1:,lb2:), ÚMYSL(V), CÍLOVÁ :: poleNEMOVITÝ, DIMENZE(:,:), POINTER                  :: ptr   ptr => poleEND FUNCTION  :okno => remap_bounds2(r,s,stůl(m:n,str:q))

The source code of an extended example of the use of pointers to support a data structure is in pointer.f90.

Intrinsic procedures

Most of the intrinsic functions have already been mentioned. Here, we deal only with their general classification and with those that have so far been omitted. All intrinsic procedures can be used with keyword arguments:

VOLÁNÍ DATE_AND_TIME (ČAS=t)

and many have optional arguments.

The intrinsic procedures are grouped into four categories:

  1. elemental - work on scalars or arrays, e.g. ABS(a);
  2. inquiry - independent of value of argument (which may be undefined), e.g. PRECISION(a);
  3. transformational - array argument with array result of different shape, e.g. RESHAPE(a, b);
  4. subroutines, e.g. SYSTEM_CLOCK.

The procedures not already introduced are

Bit inquiry

     BIT_SIZE           Number of bits in the model

Manipulace s bitem

     BTEST              Bit testing     IAND               Logical AND     IBCLR              Clear bit     IBITS              Bit extraction     IBSET              Set bit     IEOR               Exclusive OR     IOR                Inclusive OR     ISHFT              Logical shift     ISHFTC             Circular shift     NOT                Logical complement

Transfer function, as in

CELÉ ČÍSLO :: i = PŘEVOD('abeceda', 0)

(replaces part of EQUIVALENCE)

Subroutines

     DATE_AND_TIME      Obtain date and/or time     MVBITS             Copies bits     RANDOM_NUMBER      Returns pseudorandom numbers     RANDOM_SEED        Access to seed     SYSTEM_CLOCK       Access to system clock     CPU_TIME           Returns processor time in seconds

Přenos dat

(This is a subset only of the actual features and, exceptionally, lower case is usedin the code examples.)

Formatted input/output

These examples illustrate various forms of I/O lists with some simple formats (see níže ):

celé číslo             :: inemovitý, dimenze(10) :: Acharakter(len=20)   :: slovotisk "(i10)",     itisk "(10f10.3)", Atisk "(3f10.3)",  A(1),A(2),A(3)tisk "(a10)",     slovo(5:14)tisk "(3f10.3)",  A(1)*A(2)+i, čtv(A(3:4))

Variables, but not expressions, are equally valid in inputstatements using the číst prohlášení:

číst "(i10)", i

If an array appears as an item, it is treated as if the elements were specified in array element order.

Any pointers in an I/O list must be associated with a target, and transfer takes place between the file and the targets.

An item of derived type is treated as if the components were specifiedin the same order as in the type declaration, so

číst "(8f10.5)", str, t  ! types point and triangle

has the same effect as the statement

číst "(8f10.5)", str%X, str%y, t%A%X, t%A%y, t%b%X, &                           t%b%y, t%C%X, t%C%y

An object in an I/O list is not permitted to be of a derived typethat has a pointer component at any level of component selection.

Note that a zero-sized arraymay occur as an item in an I/O list.Such an item corresponds to no actual data transfer.

The format specification may alsobe given in the form of a character expression:

charakter(len=*), parametr :: formulář="(f10.3)":tisk formulář, q

or as an asterisk – this is a type of I/O known aslist-directedI/O (see níže ), in which the format is defined by the computer system:

tisk *, "Square-root of q = ", čtv(q)

Input/output operations are used to transfer data between thestorage of an executing program and an external medium, specified by a unit number.However, two I/O statements, tisk and a variant ofčíst, do notreference any unit number: this is referred to as terminal I/O. Otherwise the form is:

číst (jednotka=4,     fmt="(f10.3)") qčíst (jednotka=nunit, fmt="(f10.3)") qčíst (jednotka=4*i+j, fmt="(f10.3)") A

kde unit= is optional.The value may be any nonnegative integer allowed by the systemfor this purpose (but 0, 5 and 6 often denote the error, keyboard and terminal, respectively).

An asterisk is a variant – again from the keyboard:

číst (jednotka=*, fmt="(f10.3)") q

A read with a unit specifier allows zpracování výjimek:

číst (jednotka=nunit, fmt="(3f10.3)", iostat=ios) A,b,C-li (ios == 0) pak! Successful read - continue execution.   :jiný! Error condition - take appropriate action.   volání chyba (ios)skončit, pokud

There a second type of formatted output statement, thepsát si prohlášení:

psát si (jednotka=nout, fmt="(10f10.3)", iostat=ios) A

Internal files

These allow format conversion between various representations to be carried out by the program in a storage area defined within the program itself.

celé číslo, dimenze(30)         :: ivalcelé číslo                        :: klíčcharakter(len=30)              :: nárazníkcharakter(len=6), dimenze(3), parametr :: formulář=(/ "(30i1)", "(15i2)","(10i3)" /)číst (jednotka=*, fmt="(a30,i1)")      nárazník, klíččíst (jednotka=nárazník, fmt=formulář (klíč)) ival(1:30/klíč)

If an internal file is a scalar, it has a single record whose length is that of the scalar.

If it is an array, its elements, in array element order, are treated as successive records of the file and each has length that of an array element.

An example using a psát si statement is

celé číslo           :: dennemovitý              :: hotovostcharakter(len=50) :: čára:! write into linepsát si (jednotka=čára, fmt="(a, i2, a, f8.2, a)") "Takings for day ", den, „jsou“, hotovost, " dollars"

that might write

 Takings for day  3 are  4329.15 dollars

List-directed I/O

An example of a read without a specified format for input is

celé číslo               :: inemovitý                  :: Akomplex, dimenze(2) :: polelogický               :: vlajkacharakter(len=12)     :: titulcharakter(len=4)      :: slovo:číst *, i, A, pole, vlajka, titul, slovo

If this reads the input record

10 6.4 (1.0,0.0) (2.0,0.0) t test/

(in which blanks are used as separators),then i, A, pole, vlajka, a titul will acquire the values 10, 6.4, (1.0,0.0) and (2.0,0.0), .true.a test respectively,while slovo zůstává nezměněno.

Quotation marks or apostrophes are required as delimiters for a string thatcontains a blank.

Non-advancing I/O

This is a form of reading and writingwithout always advancing the file position to ahead of the next record.Whereas an advancing I/O statement always repositions the file after the lastrecord accessed, a non-advancing I/O statement performs nosuch repositioning and may therefore leave the file positioned within arecord.

charakter(len=3) :: klíčcelé číslo      :: u, s, ios:číst(jednotka=u, fmt="(a3)", záloha="no", velikost=s, iostat=ios) klíč-li (ios == 0) pak   :jiný! key is not in one record   klíč(s+1:) = ""   :skončit, pokud

A non-advancing read might read the firstfew characters of a record and a normal read the remainder.

In order to write a prompt to aterminal screen and to read from the next character position on thescreen without an intervening line-feed, we can write

psát si (jednotka=*, fmt="(a)", záloha="no") "enter next prime number:"číst  (jednotka=*, fmt="(i10)") prime_number

Non-advancing I/O is for external files, and is not available for list-directed I/O.

Edit descriptors

It is possible to specify that an edit descriptor be repeated a specified number of times, using a repeat count: 10f12.3

The slash edit descriptor (see níže )may have a repeat count, and a repeat count can also apply to a group of editdescriptors, enclosed in parentheses, with nesting:

tisk "(2(2i5,2f8.2))", i(1),i(2),A(1),A(2), i(3),i(4),A(3),A(4)

Entire format specifications can be repeated:

tisk "(10i8)", (/ (i(j), j=1,200) /)

writes 10 integers, each occupying 8 character positions, on each of 20 lines (repeating the format specification advances to the next line).

Data edit descriptors

  • Celé číslo: iW iW.M
  • Nemovitý: fW.D esW.D esW.DeE
  • Complex: pairs of F nebo es edit descriptors
  • Logical: lW
  • Charakter: a aW
  • Derived types: are edited by the appropriate sequence of edit descriptors corresponding to the intrinsic types of the ultimate components of the derived type.
    typ, veřejnost :: tětiva   celé číslo   :: délka   charakter(len=20) :: slovoend type tětivatyp(tětiva) :: textčíst(jednotka=*, fmt="(i2, a)") text

Control edit descriptors

Control edit descriptors setting conditions:

  • The ss (sign suppress) edit descriptor suppresses leading plus signs. To switch on plus sign printing, the sp (sign print) descriptor is used. The s edit descriptor restores the option to the processor.
  • This descriptor remains in force for the remainder of the format specification, unless another of them is met.

Control edit descriptors for immediate processing:

  • Tabulation: tN trN tlN
    číst (jednotka=*, fmt="(t3,i4, tl4,i1, i2)") i,j,k
  • New records: / N/
    číst "(i5,i3,/,i5,i3,i2)", i, j, k, l, m

    Všimněte si, že

    tisk "(i5,4/,i5)", i, j
    separates the two values by three blank records.
  • Colon editing:  :terminates format control if there are no further items inan I/O list.
    tisk "( i5, :, /, i5, :, /, i5)", (/(l(i), i=1,n)/)
    stops new records if n equals 1 or 2.

Unformatted I/O

This type of I/O should be used only in cases where the records aregenerated by a program on one computer, to be read back on the samecomputer or another computer using thesame internal number representations:

otevřeno(jednotka=4, soubor='test', formulář='unformatted')číst(jednotka=4) qpsát si(jednotka=nout, iostat=ios) A  ! no fmt=

Direct-access files

This form of I/O is also known as random access or indexed I/O.Here, all the records have the samelength, and eachrecord is identified by an index number. It is possible to write,read, or re-write any specified record without regard to position.

celé číslo, parametr :: nunit=2, délka=100nemovitý, dimenze(délka)            :: Anemovitý, dimenze(délka+1:2*délka) :: bcelé číslo                            :: i, rec_length:inquire (iolength=rec_length) Aotevřeno (jednotka=nunit, přístup="direct", recl=rec_length, postavení="scratch", akce="readwrite"):! Write array b to direct-access file in record 14psát si (jednotka=nunit, rec=14) b:!! Read the array back into array ačíst (jednotka=nunit, rec=14) A:dělat i = 1, délka/2   A(i) = iend do!! Replace modified recordpsát si (jednotka=nunit, rec=14) A

The file must be an external file and list-directed formatting and non-advancing I/O areunavailable.

Operations on external files

Once again, this is an overview only.

File positioning statements

  • The backspace prohlášení:
    backspace (jednotka=u [,iostat=ios])      ! where [ ] means optional
  • The přetočit prohlášení:
    přetočit (jednotka=u [,iostat=ios])
  • The endfile prohlášení:
    endfile (jednotka=u [,iostat=ios])

The otevřeno prohlášení

The statement is used to connect an external file to a unit,create a file that is preconnected, or create a file and connect it to aunit.The syntax is

otevřeno (jednotka=u, postavení=Svatý, akce=akt [,olist])

kde olist is a list of optional specifiers.The specifiers may appear in any order.

otevřeno (jednotka=2, iostat=ios, soubor="cities", postavení="Nový", přístup="direct",  &      akce="readwrite", recl=100)

Other specifiers are formulář a pozice.

The zavřít prohlášení

This is used to disconnect a file from a unit.

zavřít (jednotka=u [,iostat=ios] [,postavení=Svatý])

jako v

zavřít (jednotka=2, iostat=ios, postavení="vymazat")

The inquire prohlášení

At any time during the execution of a program it is possible to inquire about the status and attributes of a file using this statement.

Using a variant of this statement, it is similarly possible to determine the status of a unit, for instance whether the unit number exists for that system.

Another variant permits an inquiry about the length of an output list when used to write an unformatted record.

For inquire by unit

inquire (jednotka=u, ilist)

or for inquire by file

inquire (soubor=fln, ilist)

or for inquire by I/O list

inquire (iolength=délka) olist

Jako příklad

logický            :: např, opcharakter (len=11) :: nam, dle, násl, frmcelé číslo            :: irec, činquire (jednotka=2, existovat=např, otevřel=op, název=nam, přístup=dle, sekvenční=násl, formulář=frm, &         recl=irec, nextrec=č)

yields

např      .skutečný.op      .skutečný.nam      městadle      PŘÍMOnásl      NEfrm      UNFORMATTEDirec     100č       1

(assuming no intervening read or write operations).

Other specifiers are iostat, opened, number,named, formatted, position, action, read, write, readwrite.

Reference

  1. ^ http://www.fortranplus.co.uk/fortran-information/
  2. ^ "Modern Fortran Explained: Paperback: Michael Metcalf, John Reid, Malcolm Cohen - Oxford University Press". Ukcatalogue.oup.com (2019).