современный фортран , Бортеньев. О. В. Бартеньев Современный Фортран
Скачать 2.24 Mb.
|
143 О. В. Бартеньев. Современный ФОРТРАН print *, minval(array, dim = 1) ! 1 2 3 print *, minval(array, dim = 2) ! 1 2 ! В следующем вызове все ключевые слова опущены print *, minval(array, 1, array /= 2) ! 1 5 3 end PRODUCT(array [, dim] [, mask]) - вычисляет произведение всех элементов целочисленного или вещественного массива вдоль необязательного измерения dim. Перемножаемые элементы могут отбираться необязательной маской mask. Смысл параметра dim разъяснен при описании функции ALL, а параметра mask - при описании функции MAXLOC. Возвращаемый функцией результат имеет тот же тип и разновидность типа, что и массив array. Если размер массива array равен нулю или все элементы массива mask равны .FALSE., то результат функции равен единице. SUM(array [, dim] [, mask]) - вычисляет сумму всех элементов целочисленного или вещественного массива вдоль необязательного измерения dim. Суммируемые элементы могут отбираться необязательной маской mask. Смысл параметра dim разъяснен при описании функции ALL, а параметра mask - при описании функции MAXLOC. Возвращаемый функцией результат имеет тот же тип и разновидность типа, что и массив array. Если размер массива array равен нулю или все элементы массива mask равны .FALSE., то результат функции равен нулю. Пример для функций PRODUCT и SUM: integer arra (2, 3) /1, 4, 2, 5, 3, 6/ integer ar1(3), ar2(2) ! Массив array: 1 2 3 ! 4 5 6 ar1 = product(arra, dim = 1) ! Произведение по столбцам print *, ar1 ! 4 10 18 ar2 = product(arra, mask = arra < 6, dim = 2) print *, ar2 ! 6 20 print *, sum(arra, dim = 1) ! 5 7 9 ar2=sum(arra, mask = arra < 6, dim = 2) ! Суммирование по строчкам print *, ar2 ! 6 9 ! Произведение сумм столбцов матрицы: (1 + 4) * (2 + 5) * (3 + 6) print *, product(sum(arra, dim = 1)) ! 315 end 144 4. Массивы 4.12.2. Умножение векторов и матриц DOT_PRODUCT(vector_a, vector_b) - функция возвращает скалярное произведение векторов vector_a и vector_b, равное сумме произведений их элементов с равными значениями индексов. vector_a - одномерный массив целого, вещественного, комплексного или логического типа. vector_b - одномерный массив того же размера, что и массив vector_a. Должен быть логического типа, если массив vector_a логического типа. Должен быть числовым (целым, вещественным или комплексным), если массив vector_a числовой. В последнем случае тип vector_b может отличаться от типа vector_a. Возвращаемое число равно: • SUM(vector_a * vector_b), если vector_a целого или вещественного типа. Результат имеет целый тип, если оба аргумента целого типа; комплексный, если vector_b комплексного типа, и вещественный в противном случае; • SUM(CONJG(vector_a) * vector_b), если vector_a комплексного типа, то и результат также является комплексным числом; • ANY(vector_a .AND. vector_b), если аргументы логического типа, то и результат имеет логический тип. Если размер векторов равен нулю, то и результат равен нулю или .FALSE. в случае логического типа. Пример: print *, dot_product((/ 1, 2, 3 /), (/ 4, 5, 6 /)) ! 32 MATMUL(matrix_a, matrix_b) - выполняет по принятым в линейной алгебре правилам умножение матриц целого, вещественного, комплексного и логического типа. matrix_a - одномерный или двумерный массив целого, вещественного, комплексного или логического типа. matrix_b – массив логического типа, если matrix_a - логический массив; числовой массив, если matrix_a - числовой массив. В последнем случае тип matrix _b может отличаться от типа matrix_a. По крайней мере один из массивов matrix_a и matrix_b должен быть двумерным. Возможны 3 случая: • matrix_a имеет форму (n, m), а matrix_b имеет форму (m, k). Тогда результат имеет форму (n, k), а значение элемента (i, j) равно SUM(matrix_a(i, :) * matrix_b(:, j)); • matrix_a имеет форму (m), а matrix_b имеет форму (m, k). Тогда результат имеет форму (k), а значение элемента (j) равно SUM(matrix_a * matrix_b(:, j)); 145 О. В. Бартеньев. Современный ФОРТРАН • matrix_a имеет форму (n, m), а matrix_b имеет форму (m). Тогда результат имеет форму (n), а значение элемента (i) равно SUM(matrix_a(i, :) * matrix_b). Для логических массивов функция ANY эквивалентна функции SUM, а .AND. эквивалентен произведению (*). Пример: integer a(2, 3), b(3, 2), c(2), d(3), e(2, 2), f(3), g(2) a = reshape((/ 1, 2, 3, 4, 5, 6 /), (/ 2, 3 /)) b = reshape((/ 1, 2, 3, 4, 5, 6 /), (/ 3, 2 /)) ! Массив a: 1 3 5 ! 2 4 6 ! Массив b: 1 4 ! 2 5 ! 3 6 c = (/ 1, 2 /) d = (/ 1, 2, 3 /) e = matmul(a, b) ! Результат: 22 49 ! 28 64 f = matmul(c, a) ! Результат: 5 11 17 g = matmul(a, d) ! Результат: 22 28 Из линейной алгебры известно, что произведением вектор-столбца x на вектор-строку y T является матрица ( ) n m T m m xy y y y x x x A × ∈ = ⎟ ⎟ ⎟ ⎟ ⎟ ⎠ ⎞ ⎜ ⎜ ⎜ ⎜ ⎜ ⎝ ⎛ = R 2 1 2 1 В Фортране ее вернет встроенная функция MATMUL. Правда, для обеспечения ее работоспособности потребуется преобразовать вектор x в массив формы (/ m, 1 /), а вектор y T - в массив формы (/ 1, n /): integer(4), parameter :: m = 3, n = 5 integer(4) :: i, j real(4) :: x(m) = (/ 1.0, 2.0, 3.0 /) real(4) :: y(n) = (/ 5.0, 6.0, 7.0, 8.0, 9.0 /) real(4) :: a(m, n) = 0.0 a = matmul(reshape(x, shape = (/ m, 1 /)), reshape(y, shape = (/ 1, n /))) do i = 1, m ! Вывод результата print '(1x, 10f6.2)', a(i, :) end do ! Тот же результат, но быстрее, даст вложенный цикл do j = 1, n do i = 1, m a(i, j) = x(i) * y(j) end do end do 146 4. Массивы Результат: 5.00 6.00 7.00 8.00 9.00 10.00 12.00 14.00 16.00 18.00 15.00 18.00 21.00 24.00 27.00 Замечание. Рассмотренное умножение вектор-столбца x на вектор-строку y T называют внешним произведением. Ранг внешнего произведения, когда x и y действительные векторы, не выше единицы. 4.12.3. Справочные функции для массивов 4.12.3.1. Статус размещаемого массива ALLOCATED(array) - возвращает значение стандартного логического типа, равное .TRUE., если размещаемый массив array (массив, имеющий атрибут ALLOCATABLE) в данный момент размещен, и .FALSE. - в противном случае. Результат будет неопределенным, если не определен статус размещаемого массива. Возникнет ошибка компиляции, если параметром функции окажется массив, не имеющий атрибут ALLOCATABLE, или скаляр. 4.12.3.2. Граница, форма и размер массива Функции этого раздела выдают информацию о границах массива любого типа. Если параметром является размещаемый массив, то он должен быть размещен, а если ссылка, то она должна быть прикреплена к адресату. Нижние границы сечения массива считаются равными единице, а верхние - равными соответствующим экстентам. Поскольку результат зависит только от свойств массива, то его значение необязательно должно быть определенным. В функциях этого подраздела (кроме функции SHAPE) параметр dim - целое константное выражение; 1 ≤ dim ≤ n, где n - ранг массива - аргумента функции. LBOUND(array [, dim]) - если параметр dim отсутствует, то возвращается одномерный массив стандартного целого типа, содержащий нижние границы всех измерений. Размерность массива-результата при отсутствии dim равна рангу массива array. Если dim задан, то результатом является скаляр, равный нижней границе размерности dim массива array. Если array - перенимающий размер массив, то параметр dim должен быть задан и не должен задавать последнюю размерность массива array. dim - целочисленное константное выражение; 1 ≤ dim ≤ n, где n - ранг массива array. UBOUND(array [, dim]) - подобна LBOUND, но возвращает верхние границы. Пример: real array (2:8, 8:14) integer, allocatable :: lb(:) allocate( lb(size(shape(array))) ) 147 О. В. Бартеньев. Современный ФОРТРАН lb = lbound(array) print *, lb ! 2 8 print *, lbound(array, dim = 2) ! 8 print *, lbound(array(2:6:2, 10:12)) ! 1 1 lb = ubound(array) print *, lb ! 8 14 print *, ubound(array, dim = 2) ! 14 print *, ubound(array(:6:2, 10:12)) ! 3 3 end SHAPE(source) - возвращает одномерный массив стандартного целого типа, содержащий форму массива или скаляра source. Source может иметь любой тип и не может быть перенимающим размер массивом. Размер массива-результата равен рангу source. Пример: integer vec(2), array(3:10, -1:3) vec = shape(array) write(*, *) vec ! 8 5 SIZE(array [, dim]) - возвращает стандартное целое, равное размеру массива array,или, если присутствует скалярный целый параметр dim, число элементов (экстент) вдоль заданного измерения dim. Если array - перенимающий размер массив, параметр dim должен быть задан. Пример: real(8) array (3:10, -1:3) integer i, j i = size(array, dim = 2) ! Возвращает 5 j = size(array) ! Возвращает 40 4.12.4. Функции преобразования массивов 4.12.4.1. Элементная функция MERGE слияния массивов MERGE(tsource, fsource, mask) - создает согласно заданной маске новый массив из элементов двух массивов. tsource, fsource - массивы одной формы, одного (любого) типа и параметра типа, из которых берутся элементы в массив-результат. mask - логический массив той же формы, которую имеют массивы tsource и fsource. Массив mask определяет, из какого массива, tsource или fsource, будет взят в массив-результат очередной элемент. Функция MERGE возвращает массив той же формы и того же типа, что и массивы tsource и fsource. В массив-результат поступает элемент массива tsource, если соответствующий ему элемент в массиве mask равен .TRUE., в противном случае в результат поступает элемент из массива fsource. Пример: 148 4. Массивы integer tsource(2, 3), fsource(2, 3), ar1 (2, 3) logical mask(2, 3) tsource = reshape((/1, 4, 2, 5, 3, 6/), (/2, 3/)) fsource = reshape((/7, 0, 8, -1, 9, -2/), (/2, 3/)) mask = reshape((/.true., .false., .false., .true., .true., .false./), (/2,3/)) ! tsource: 1 2 3 fsource: 7 8 9 mask: .true. .false. .true. ! 4 5 6 0 -1 -2 .false. .true. .false. ar1 = merge(tsource, fsource, mask) ! Результат: 1 8 3 end ! 0 5 -2 Замечание. Параметр tsource или fsource может быть и скаляром, который по правилам элементности будет расширен в массив надлежащей формы, например: integer tsource(5) / 1, 2, 3, 4, 5 /, fsource / 7 / logical mask(5) / .true., .false., .false., .true., .true. / print *, merge(tsource, fsource, mask) ! 1 7 7 4 5 end 4.12.4.2. Упаковка и распаковка массивов PACK(array, mask [, vector]) - упаковывает массив в одномерный массив (вектор) под управлением массива mask. array - массив любого типа, который пакуется в вектор. mask - логический массив той же формы, которую имеет и array,или просто логическая величина .TRUE.; mask - задает условия упаковки элементов массива array. vector - необязательный одномерный массив, имеющий тот же тип и разновидность типа, что и массив array. Число элементов в массиве не должно быть меньше количества элементов со значением .TRUE. в массиве mask. Функция возвращает одномерный массив того же типа и разновидности типа, что и массив array, и того же размера, что и массив vector, если последний задан. Значение первого элемента в массиве-результате - элемент массива array, который соответствует элементу со значением .TRUE. в mask; второй элемент в массиве-результате - элемент массива array, который соответствует второму элементу со значением .TRUE. в mask,и т. д. Элементы просматриваются в порядке их размещения в памяти ЭВМ (быстрее всего изменяется самый левый индекс). Если vector опущен, то размер результирующего массива равен числу элементов со значением .TRUE. в mask. Если же параметр mask задан единственным значением .TRUE., то размер результата равен размеру массива array. Если vector задан и имеет размер, больший числа элементов со значением .TRUE. в mask, то дополнительные элементы массива vector копируются без изменений в результат. 149 О. В. Бартеньев. Современный ФОРТРАН Пример: integer array(2, 3), vec1(2), vec2(5) logical mask (2, 3) array = reshape((/ 7, 0, 0, -5, 0, 0 /), (/ 2, 3 /)) mask = array /= 0 ! Массив array: 7 0 0 Массив mask: . true. . false. . false. ! 0 -5 0 .false. .true. false. vec1 = pack(array, mask) vec2 = pack(array, mask = array > 0, vector = (/ 1, 2, 3, 4, 5 /)) print *, vec1 ! 7 -5 print *, vec2 ! 7 2 3 4 5 end UNPACK(vector, mask, field) - возвращает массив того же типа и разновидности типа, как и у одномерного массива vector, и той же формы, что у логического массива mask. Число элементов vector по меньшей мере равно числу истинных элементов массива mask. Параметр field должен быть скаляром либо иметь ту же форму, которую имеет и массив mask, а его тип и параметры типа должны быть такими же, как у vector. Элемент результата, соответствующий i-му истинному элементу массива mask, считая в порядке следования его элементов, равен i-му элементу vec- tor, а все остальные элементы равны соответствующим элементам field, если это массив, или собственно field, если это скаляр. Пример: logical mask (2, 3) integer vector(3) /1, 2, 3/, ar1(2, 3) mask = reshape((/ .true., .false., .false., .true., .true., .false. /), (/ 2, 3 /)) ! Массив vector: 1 2 3 Массив mask: . true. . false. . true. ! .false. .true. false. ar1 = unpack(vector, mask, 8) print *, ar1(1, :) ! Результат: 1 8 3 print *, ar1(2, :) ! 8 2 8 end 4.12.4.3. Переформирование массива RESHAPE(source, shape [, pad] [, order]) - формирует массив заданной формы shape из элементов массива source. Результирующий массив имеет тот же тип и разновидность типа, что и source. source - массив любого типа, элементы которого берутся в порядке их следования для формирования нового массива. shape - одномерный целочисленный массив, задающий форму результата: i-й элемент shape равен размеру i-го измерения формируемого массива. Если pad опущен, общий задаваемый shape размер не должен превышать размера source. 150 4. Массивы pad - необязательный массив того же типа, что и source. Если в source недостает элементов для формирования результата, элементы pad добавляются в результирующий массив в порядке их следования. При необходимости используются дополнительные копии pad для заполнения результата. order - необязательный одномерный массив того же размера, что и shape. Переставляет порядок измерений (что изменяет порядок заполнения) массива-результата. Значениями order должна быть одна из перестановок вида (1, 2, ..., n), где n - размер shape; order задает порядок изменения индексов при заполнении результата. Быстрее всего изменяется индекс order(1), медленнее всего - order(n). При этом элементы из source выбираются в нормальном порядке. Далее при нехватке элементов source следуют копии элементов pad. Параметр order позволяет, в частности, переформировывать массивы в принятом в СИ порядке с последующей их передачей в СИ-функцию. Пример: integer ar1(2, 5) real f(5,3,8), c(8,3,5) ar1 = reshape((/ 1, 2, 3, 4, 5, 6 /), (/ 2, 5 /), (/ 0, 0 /), (/ 2, 1 /)) print *, ar1(1, :) print *, ar1(2, :) ! Результат: 1 2 3 4 5 ! 6 0 1 0 1 ! Изменим принятый в Фортране порядок на порядок, принятый в СИ c = reshape(f, (/ 8, 3, 5 /), order = (/ 3, 2, 1 /)) 4.12.4.4. Построение массива из копий исходного массива SPREAD(source, dim, ncopies) - повторяет массив source вдоль заданного измерения в массиве-результате, ранг которого на единицу больше source. source - массив или скалярная величина любого типа. dim - целый скаляр, задающий измерение, вдоль которого будет повторен source; 1 ≤ dim ≤ n+1, где n - число измерений в source. ncopies - число повторений source; равняется размеру экстента добавляемого измерения. Функция возвращает массив того же типа и разновидности типа, что и у source. Если source скаляр, то элемент результата равен собственно source. Результат содержит MAX(ncopies, 0) копий source. Пример: integer ar1(2, 3), ar2(3, 2) ar1 = spread((/ 1, 2, 3 /), dim=1, ncopies=2) ! Результат: 1 2 3 ! 1 2 3 ar2 = spread((/ 1, 2, 3 /), 2, 2) ! Результат: 1 1 |