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é slovo | PŘ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É ČÍSLO
s; 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 CHARAKTER
sa 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
ACHAR | IACHAR (pro sadu ASCII) |
NASTAVIT | NASTAVIT |
LEN_TRIM | INDEX (s1, s2, BACK = .TRUE.) |
OPAKOVAT | SKENOVAT (pro jednu ze sady) |
TRIM | OVĚŘ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, mě
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É ČÍSLO
s 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ýsledekANINT
: zaokrouhlit na nejbližší celé číslo, vrátit skutečný výsledekINT
: zkrátit (zaokrouhlit na nulu), vrátit celočíselný výsledekAINT
: zkrátit (zaokrouhlit na nulu), vrátit skutečný výsledekSTROP
: 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
, LEN
a čí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ýkoliNĚKDE JINDE
prohlášení, které obsahuje; - A
KDE
konstrukce může obsahovat libovolný počet maskovanýchNĚKDE JINDE
prohlášení, ale nanejvýš jednoNĚKDE JINDE
prohlášení bez masky, a to musí být poslední; KDE
konstrukty mohou být vnořeny do sebe, jenPRO 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 KDE
Postupy 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 = t
is 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:
- elemental - work on scalars or arrays, e.g.
ABS(a)
; - inquiry - independent of value of argument (which may be undefined), e.g.
PRECISION(a)
; - transformational - array argument with array result of different shape, e.g.
RESHAPE(a, b)
; - 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
neboes
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, thesp
(sign print) descriptor is used. Thes
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
separates the two values by three blank records.tisk "(i5,4/,i5)", i, j
- Colon editing:
:
terminates format control if there are no further items inan I/O list.stops new records iftisk "( i5, :, /, i5, :, /, i5)", (/(l(i), i=1,n)/)
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
.