Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
современный фортран , Бортеньев.pdf
Скачиваний:
242
Добавлен:
26.03.2015
Размер:
2.34 Mб
Скачать

О. В. Бартеньев. Современный ФОРТРАН

integer(4), intent(in) :: k, m ! Формальные параметры чистой функции decr = real(m) / real(k) ! должны иметь вид связи INTENT(IN) end function decr

program pudem

real(4), dimension(5, 5) :: array = 5.0 interface

pure function decr(k, m)

! Поскольку функция используется в FORALL,

real(4) :: decr

! то необходимо задать ее интерфейс

integer(4), intent(in) :: k, m

 

end function decr

 

end interface

forall(i = 1:5, j = 1:5) array(i, j) = decr(i, j)

print '(10f5.1)', array(1, :)

! 1.0 2.0 3.0 4.0 5.0

end program pudem

 

Замечание. Чистые процедуры введены стандартом 1995 г.

8.26. Элементные процедуры

Элементные пользовательские процедуры подобно встроенным элементным процедурам могут иметь в качестве фактических параметров либо скаляры, либо массивы. В последнем случае массивы должны быть согласованы, т. е. иметь одинаковую форму; результатом процедуры является поэлементная обработка массивов - фактических параметров. Приведем пример выполнения встроенной элементной функции MOD, возвращающей остаток от деления первого параметра на второй:

integer(4), dimension(5) :: a = (/ 1, 2, 3, 4, 5 /), b = (/ 1, 2, -2, 4, 3 /), c

integer(4) :: d

 

 

 

c = mod(a, b)

! Параметры функции - массивы

print *, c

!

0

0 1 0 2

d = mod(b(4), a(3))

! Параметры функции - скаляры

print *, d

!

1

 

Программная единица, вызывающая элементную функцию, должна содержать ее интерфейс, в котором явно указано слово ELEMENTAL. Цель введения элементных функций - упростить распараллеливание вычислений на многопроцессорных машинах: компилятор, имеющий сведения о том, что функция элементная, выполняет распараллеливание по заложенным в него правилам.

Элементные функции - это чистые функции, имеющие только скалярные формальные параметры, не являющиеся ссылками или процедурами. Вид связи параметров - INTENT(IN). Результирующая переменная элементной функции также является скаляром и не может быть ссылкой. Элементная функция снабжается ключевым словом ELEMENTAL, которое автоматически подразумевает ключевое слово PURE. Элементные функции не могут быть оснащены ключевым словом RECURSIVE.

284

8. Программные единицы

Если фактическими параметрами элементной функции являются массивы, то они должны быть согласованы; результатом такой функции является массив, согласованный с массивами-параметрами.

Пример:

elemental integer(4) function find_c(a, b)

integer(4), intent(in) :: a, b ! Не забываем задать вид связи INTENT(IN) if(a > b) then

find_c = a

else if(b < 0) then find_c = abs(b) else

find_c = 0 end if

end function find_c

program etest

 

interface

! Интерфейс обязателен

elemental integer(4) function find_c(a, b)

integer(4), intent(in) :: a, b

! Обязательное задание вида связи INTENT(IN)

end function find_c

 

end interface

integer(4), dimension(5) :: a = (/ -1, 2, -3, 4, 5 /), b = (/ 1, 2, -2, 4, 3 /), c

integer(4) :: d = 5

 

 

 

c = find_c(a, b)

! Параметры функции - массивы

print *, c

!

0

0 2 0 5

d = find_c(-1, 1)

! Параметры функции - скаляры

print *, d

!

0

 

end program etest

 

 

 

Замечание. Поскольку элементные функции являются чистыми, они могут быть использованы в операторе и конструкции FORALL.

Элементные подпрограммы задаются подобно элементным функциям. В теле процедуры могут изменяться параметры с видом связи OUT иINOUT.

Пример:

elemental subroutine find_c(a, b, c) integer(4), intent(in) :: a, b integer(4), intent(out) :: c

if(a > b) then c = a

else if(b < 0) then c = abs(b)

else c = 0

285

О. В. Бартеньев. Современный ФОРТРАН

end if

end subroutine find_c

program etest2 interface

elemental subroutine find_c(a, b, c) integer(4), intent(in) :: a, b integer(4), intent(out) :: c

end subroutine end interface

integer(4), dimension(5) :: a = (/ -1, 2, -3, 4, 5 /), b = (/ 1, 2, -2, 4, 3 /), c integer(4) :: d = 5

286

! Вывод x без перехода на новую строку
! Вывод z без перехода на новую строку
! Переход на новую строку

 

 

 

8. Программные единицы

call find_c(a, b, c)

! Параметры и результат - массивы

print *, c

!

0

0 2 0 5

call find_c(-1, 1, d)

! Параметры и результат - скаляры

print *, d

!

0

 

end program etest2

 

 

 

Замечание. Элементные процедуры введены стандартом 1995 г.

8.27. Операторные функции

Если некоторое выражение встречается в программной единице неоднократно, то его можно оформить в виде операторнойфункции изаменить все вхождения выражения на эту функцию. Операторные функции задаются так:

имя функции ([список формальных параметров]) = выражение

Если список формальных параметров содержит более одного имени, то имена разделяются запятыми.

Как и встроенная или внешняя функция, операторная функция вызывается в выражении. Областью видимости операторной функции является программная единица, в которой эта функция определена. В то же время операторная функция может быть доступна в других программных единицах за счет ассоциирования через носитель или use-ассоциирования, но не может быть ассоциирована через параметры процедуры. Тип операторной функции следует объявлять явно, размещая ее имя в операторе объявления типа или в операторе IMPLICIT.

Пример. Выполнить табуляцию функции z = siny * e-x.

real(8) :: x = -1.0_8, y, z

! Используем двойную точность

real(8) :: dx = 0.4_8, dy = 0.3_8

! Задание операторной функции z(x, y)

z(x, y) = exp(-x) * sin(y)

write(*, '(6h x/y , 20f8.2)') (y, y = -0.6, 0.6, 0.3) do while(x <= 1.0_8)

write(*, '(f6.2 \)') x y = -0.60_8

do while(y <= 0.6_8) write(*, '(f8.2 \)') z(x, y) y = y + dy

end do

x = x + dx write(*, *) end do end

Замечание. Для вывода без продвижения на новую строку используется преобразование обратного слеша (\).

287