Pokročilá práce s poli
V částech podmínky a cykly jsem zmínil základní prvky jazyka fortran, které se dají použít obecně pro všechny struktury. Fortran ovšem poskytuje další funkce, které jsou speciálně navržené pro práci s poli.
příkaz where
Přikaz kombinuje cyklus s podminkou a slouží převážně k přiřazování hodnot prvkům pole. Podmínky musí být buď pole logical
stejného tvaru jako pole v kódu nebo podmínka aplikovatelná na každý prvek pole v kódu.
where (podmínka1)
...kód...
else where (podmínka2)
...další kód...
end where
program stat_where
implicit none
real :: a(10),b(10),c(10)
call random_number(a)
call random_number(b)
a = nint(a)*1.
b = nint(10.*b)*1.
write(*,'(10f7.1)') a
write(*,'(10f7.1)') b
where(a /= 0.)
c = b/a
else where
c = 1.
end where
write(*,'(10f7.1)') c
end program
příkaz do concurrent
Příkaz je jako příkaz do
až na to, že nemusí procházet pole postupně. Příkaz vznikl pro tzv. autoparelelizaci kompilérů. Oproti příkazů do
by měl být rychlejší, ale jsou na něj kladena omezení. Např. uvnitř se smí používat jen pure funkce, aby se zabránilo vedlejším efektům, které by narušovali paralelní běh. Tento příkaz přišel s Fortranem 2008 a má nahradit příkaz forall
, který je téměř stejný.
do concurrent (i = L:U)
...příkazy pracující s polem...
end forall
program do_concurrent
use iso_fortran_env
implicit none
integer,parameter :: n = 10000
integer :: i,j
real :: t1, t2
real :: a(n),c(n,n)
call random_number(a)
call cpu_time(t1)
do i=1,n
do j=1,n
c(i,j) = a(i) - a(j)
end do
end do
call cpu_time(t2)
write(*,*) "do ", t2-t1
call cpu_time(t1)
do concurrent (i=1:n, j=1:n)
c(i,j) = a(i) - a(j)
end do
call cpu_time(t2)
write(*,*) "do concurrent ", t2-t1
end program
další vnitřní funkce s poli
Zde následuje výčet dalších funkcí, které fortran podporuje. Tento seznam nemusí být úplný a některé funkce používájí další volitelné argumenty. V případě, že budete potřebovat podrobnější informace doporučuji se podívat do manuálu kompilátoru, který používáte. (V hranatých závorkách [] jsou vepoviné argumenty). Výraz mask
je pole logických výrazů (např. pole A > pole B = ṕole logical
apod.).
all(mask)
- vrátí.true.
pokud všechny prvky masky jsou.true.
any(mask)
- vrátí.true.
pokud některý prvek masky je.true.
count(mask)
- vrátí počet (integer
) prvků masky rovnající se.true.
merge(A, B, mask)
- sloučí pole A a B podle masky. Pokud prvek masky je.true.
je prvek výstupního pole prvek pole A jinak prvek pole Bpack(A, mask [,vector])
- vytvoří nám jednorozměrné pole skládající se z prvků pole A tam kde je maska.true.
. Maska může být jen skalární.true.
, potom může převést vícerozměrné pole na jednorozměrné pole. Pokud zadáme vector, doplní se prvky z polevector
aby výsledné pole mělo stejný počet prvků jako pole Aunpack(vector, mask [, field])
- rozbalý vektor (1D pole) do tvaru a velikosti masky. Pokud zadáme field výsledné pole bude mít prvek z pole vector tam kde je maska.true.
a tam kde je.false.
prvek z pole fieldreshape(A, tvar)
- změní tvar pole A na zadaný tvar tvar