行列積、ドット積、および配列シフト#

cshift#

名前#

cshift(3) - [変換] 配列の要素を循環シフトする

概要#

   result = cshift(array, shift [,dim])
    type(TYPE, kind=KIND) function cshift(array, shift, dim )

     type(TYPE,kind=KIND),intent(in) :: array(..)
     integer(kind=**),intent(in)  :: shift
     integer(kind=**),intent(in)  :: dim

特性#

  • array は任意の型とランクを持つことができます

  • shift は、array のランクが 1 の場合は _integer_ スカラーです。それ以外の場合は、スカラーまたはランク n-1 であり、形状が [d1, d2, …, dDIM-1, dDIM+1, …, dn] である必要があります。ここで、[d1, d2, …, dn] は array の形状です。

  • dim は、1 <= dim <= n の範囲の値を持つ _integer_ スカラーです。ここで、n は array のランクです。 dim がない場合は、値 1 がある場合と同じです。

  • 結果は、array と同じ型、種別、形状になります。

注: ** で指定された種別は、その型でサポートされている任意の種別になる可能性があります

説明#

cshift(3) は、dim の次元に沿って array の要素に対して循環シフトを実行します。 dim が省略された場合は、1 とみなされます。 dim は、1 <= dim <= n の範囲の _integer_ 型のスカラーです。ここで、「n」は array のランクです。

array のランクが 1 の場合、array のすべての要素は shift の数だけシフトされます。ランクが 1 より大きい場合、指定された次元に沿った array の完全なランク 1 セクションはすべてシフトされます。ランク 1 セクションの一方の端からシフトアウトされた要素は、もう一方の端に戻ってシフトされます。

オプション#

  • array

    シフトする任意の型の配列

  • shift

    循環シフトする位置の数。負の値は右シフトを生成し、正の値は左シフトを生成します。

  • dim

    多ランク array をシフトする次元。デフォルトは 1 です。

結果#

array 引数と同じ型とランクの配列を返します。

ランク 2 の配列の行は、すべて同じ量または異なる量だけシフトできます。

cshift#

#

サンプルプログラム

program demo_cshift
implicit none
integer, dimension(5)   :: i1,i2,i3
integer, dimension(3,4) :: a, b
   !basics
    i1=[10,20,30,40,50]
    print *,'start with:'
    print '(1x,5i3)', i1
    print *,'shift -2'
    print '(1x,5i3)', cshift(i1,-2)
    print *,'shift +2'
    print '(1x,5i3)', cshift(i1,+2)

    print *,'start with a matrix'
    a = reshape( [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ], [ 3, 4 ])
    print '(4i3)', a(1,:)
    print '(4i3)', a(2,:)
    print '(4i3)', a(3,:)
    print *,'matrix shifted along rows, each by its own amount [-1,0,1]'
    b = cshift(a, SHIFT=[1, 0, -1], DIM=2)
    print *
    print '(4i3)', b(1,:)
    print '(4i3)', b(2,:)
    print '(4i3)', b(3,:)
end program demo_cshift

結果

 >  start with:
 >   10 20 30 40 50
 >  shift -2
 >   40 50 10 20 30
 >  shift +2
 >   30 40 50 10 20
 >  start with a matrix
 >   1  4  7 10
 >   2  5  8 11
 >   3  6  9 12
 >  matrix shifted along rows, each by its own amount
 >
 >   4  7 10  1
 >   2  5  8 11
 >  12  3  6  9

標準#

Fortran 95

関連項目#

  • eoshift(3) - 配列の要素を端からシフトする

  • sum(3) - 配列の要素の合計

  • product(3) - 配列要素の積

  • findloc(3) - 値を持つ次元 DIM に沿って MASK によって識別される ARRAY の最初の要素の位置

  • maxloc(3) - 配列内の最大値の位置

fortran-lang の組み込み関数の説明

dot_product#

名前#

dot_product(3) - [変換] 2つのベクトルのドット積

概要#

    result = dot_product(vector_a, vector_b)
     TYPE(kind=KIND) function dot_product(vector_a, vector_b)

      TYPE(kind=KIND),intent(in) :: vector_a(:)
      TYPE(kind=KIND),intent(in) :: vector_b(:)

特性#

  • vector_a, vector_b は、同じサイズのランク 1 の任意の数値型または論理型の配列であることができます

  • 2つのベクトルは同じ種別である必要はありませんが、特定の呼び出しでは両方とも論理型または数値型である必要があります。

  • 結果は、他のベクトルが異なる場合に必要に応じて昇格される、より高い型のベクトルの型と種別になります。

2つのベクトルは、数値型または論理型のいずれかであり、ランク 1 でサイズが等しい配列である必要があります。

説明#

dot_product(3) は、2つのベクトル vector_avector_b のドット積を計算します。

オプション#

  • vector_a

    値のランク 1 のベクトル

  • vector_b

    vector_a が数値型の場合は数値型、または vector_a が _logical_ 型の場合は _logical_ 型である必要があります。vector_b は、vector_a と同じサイズのランク 1 の配列である必要があります。

結果#

引数が数値型の場合、戻り値は数値型のスカラーです。引数が _logical_ 型の場合、戻り値は _true._ または _false._ です。

ベクトルが _integer_ または _real_ の場合、結果は

     sum(vector_a*vector_b)

ベクトルが _complex_ の場合、結果は

     sum(conjg(vector_a)*vector_b)**

ベクトルが _logical_ の場合、結果は

     any(vector_a .and. vector_b)

#

サンプルプログラム

program demo_dot_prod
implicit none
    integer, dimension(3) :: a, b
    a = [ 1, 2, 3 ]
    b = [ 4, 5, 6 ]
    print '(3i3)', a
    print *
    print '(3i3)', b
    print *
    print *, dot_product(a,b)
end program demo_dot_prod

結果

  >  1  2  3
  >
  >  4  5  6
  >
  >           32

標準#

Fortran 95

関連項目#

sum(3), conjg(3), any(3)

fortran-lang の組み込み関数の説明 (ライセンス: MIT) @urbanjost

eoshift#

名前#

eoshift(3) - [変換] 配列の要素を端からシフトする

概要#

  result = eoshift( array, shift [,boundary] [,dim] )
   type(TYPE(kind=KIND)) function eoshift(array,shift,boundary,dim)

    type(TYPE(kind=KIND)),intent(in) :: array(..)
    integer(kind=**),intent(in)      :: shift(..)
    type(TYPE(kind=KIND)),intent(in) :: boundary(..)
    integer(kind=**),intent(in)      :: dim

特性#

  • array 任意の型の配列

  • shift は任意の種の整数です。スカラーである可能性があります。 array のランクが 1 より大きく、dim が指定されている場合、array から次元 dim を削除した同じ形状になります。

  • boundary は、array と同じ型と種別のスカラーにすることができます。 array のランクが 1 の場合はスカラーでなければなりません。それ以外の場合は、次元 dim で削減された array と同じ形状の配列にすることができます。以下で説明するように、特定の型の場合にのみ欠落している可能性があります。

  • dim は任意の種類の整数です。デフォルトは 1 です。

  • 結果は、array と同じ型、型パラメーター、および形状を持ちます。

  • ** で指定された種別は、その型でサポートされている任意の種別になる可能性があります

  • 結果は、array 引数と同じ型、種別、ランクの配列になります。

説明#

eoshift(3) は、dim の次元に沿って array の要素に対して端からシフトを実行します。

ランク 1 セクションの一方の端からシフトアウトされた要素は削除されます。

boundary が存在する場合は、boundary からの対応する値がもう一方の端にコピーされます。それ以外の場合は、デフォルト値が使用されます。

オプション#

  • array

    要素をシフトする任意の型の配列。 array のランクが 1 の場合、array のすべての要素は shift の数だけシフトされます。ランクが 1 より大きい場合、指定された次元に沿った array の完全なランク 1 セクションはすべてシフトされます。

  • shift

    シフトする要素の数。負の値はベクトルの右にシフトし、正の値はシフトされるベクトルの左にシフトします。

  • boundary

    シフトによって空になった要素を埋めるために使用する値。 boundary がない場合、array の型に応じて以下がコピーされます。

    Array Type    | Boundary Value
    -----------------------------------------------------
    Numeric       | 0, 0.0, or (0.0, 0.0) of the type and kind of "array"
    Logical       | .false.
    Character(len)|  LEN blanks

これらは、boundary が存在しない可能性がある唯一の型です。これらの型の場合、種別は必要に応じて array の種別に変換されます。

  • dim

    dim は、の範囲内です

    1 <= DIM <= n

ここで、“n”array のランクです。 dim が省略された場合は、1 とみなされます。

結果#

指定された方向で、指定された数の要素を削除し、空になった要素を境界値で指定された値で埋め戻す、入力と同じ特性を持つ配列を返します。

#

サンプルプログラム

program demo_eoshift
implicit none
integer, dimension(3,3) :: a
integer :: i

    a = reshape( [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ], [ 3, 3 ])
    print '(3i3)', (a(i,:),i=1,3)

    print *

    ! shift it
    a = eoshift(a, SHIFT=[1, 2, 1], BOUNDARY=-5, DIM=2)
    print '(3i3)', (a(i,:),i=1,3)

end program demo_eoshift

結果

  >  1  4  7
  >  2  5  8
  >  3  6  9
  >
  >  4  7 -5
  >  8 -5 -5
  >  6  9 -5

標準#

Fortran 95

関連事項#

dshiftr(3), dshiftl(3)

fortran-lang の組み込み関数の説明 (ライセンス: MIT) @urbanjost

matmul#

名前#

matmul(3) - [変換関数] 数値または論理型の行列積

概要#

    result = matmul(matrix_a,matrix_b)
     function matmul(matrix_a, matrix_b)

      type(TYPE1(kind=**)       :: matrix_a(..)
      type(TYPE2(kind=**)       :: matrix_b(..)
      type(TYPE(kind=PROMOTED)) :: matmul(..)

特性#

  • matrix_aは、数値型(integerreal、またはcomplex)または論理型のランク1または2の配列です。

  • matrix_bは、数値型(integerreal、またはcomplex)または論理型のランク1または2の配列です。

  • 少なくとも1つの引数はランク2でなければなりません。

  • matrix_bの最初の次元のサイズは、matrix_aの最後の次元のサイズと等しくなければなりません。

  • 結果の型は、各引数の要素がRHS式として乗算された場合と同じです(つまり、引数が同じ型でない場合、結果は2つの型の単純なスカラー乗算で生成されるのと同じ昇格規則に従います)。

  • 一方の引数が論理型の場合、両方とも論理型でなければなりません。論理型の場合、結果の型は、配列の要素に対して.and.演算子が使用された場合と同じです。

  • 結果の形状は、以下で説明するように引数の形状によって異なります。

説明#

matmul(3)は、数値または論理型の引数に対して行列積を実行します。

オプション#

  • matrix_a

    ランクが1または2の数値型または論理型の配列。

  • matrix_b

    ランクが1または2の数値型または論理型の配列。matrix_aの最後の次元とmatrix_bの最初の次元は等しくなければなりません。

    matrix_amatrix_bは異なる数値型である可能性があることに注意してください。

結果#

数値引数#

matrix_amatrix_bが数値型の場合、結果はmatrix_amatrix_bの従来どおりの行列積を含む配列になります。

まず、数値式C=matmul(A,B)の場合

  • 任意のベクトルA(n)は、行ベクトルA(1,n)として扱われます。

  • 任意のベクトルB(n)は、列ベクトルB(n,1)として扱われます。

形状とランク#

結果の形状は、最初の行列の行数と2番目の行列の列数として決定できます。ただし、引数のいずれかがランク1(ベクトル)の場合、結果もランク1になります。逆に、両方の引数がランク2の場合、結果はランク2になります。つまり...

  • matrix_aの形状が[n,m]で、matrix_bの形状が[m,k]の場合、結果の形状は[n,k]になります。

  • matrix_aの形状が[m]で、matrix_bの形状が[m,k]の場合、結果の形状は[k]になります。

  • matrix_aの形状が[n,m]で、matrix_bの形状が[m]の場合、結果の形状は[n]になります。

#

積の要素C(i,j)は、Aのi番目の行とBのj番目の列のエントリを項ごとに乗算し、これらの積を合計することで取得されます。言い換えれば、C(i,j)は、Aのi番目の行とBのj番目の列の内積です。

論理引数#

#

matrix_amatrix_bが論理型の場合、結果の配列要素は代わりに次のようになります。

  Value_of_Element (i,j) = &
  ANY( (row_i_of_MATRIX_A) .AND. (column_j_of_MATRIX_B) )

#

サンプルプログラム

program demo_matmul
implicit none
integer :: a(2,3), b(3,2), c(2), d(3), e(2,2), f(3), g(2), v1(4),v2(4)
   a = reshape([1, 2, 3, 4, 5, 6], [2, 3])
   b = reshape([10, 20, 30, 40, 50, 60], [3, 2])
   c = [1, 2]
   d = [1, 2, 3]
   e = matmul(a, b)
   f = matmul(c,a)
   g = matmul(a,d)

   call print_matrix_int('A is ',a)
   call print_matrix_int('B is ',b)
   call print_vector_int('C is ',c)
   call print_vector_int('D is ',d)
   call print_matrix_int('E is matmul(A,B)',e)
   call print_vector_int('F is matmul(C,A)',f)
   call print_vector_int('G is matmul(A,D)',g)

   ! look at argument shapes when one is a vector
   write(*,'(" > shape")')
   ! at least one argument must be of rank two
   ! so for two vectors at least one must be reshaped
   v1=[11,22,33,44]
   v2=[10,20,30,40]

   ! these return a vector C(1:1)
   ! treat A(1:n) as A(1:1,1:n)
   call print_vector_int('Cd is a vector (not a scalar)',&
   & matmul(reshape(v1,[1,size(v1)]),v2))
   ! or treat B(1:m) as B(1:m,1:1)
   call print_vector_int('cD is a vector too',&
   & matmul(v1,reshape(v2,[size(v2),1])))

   ! or treat A(1:n) as A(1:1,1:n) and B(1:m) as B(1:m,1:1)
   ! but note this returns a matrix C(1:1,1:1) not a vector!
   call print_matrix_int('CD is a matrix',matmul(&
   & reshape(v1,[1,size(v1)]), &
   & reshape(v2,[size(v2),1])))

contains

! CONVENIENCE ROUTINES TO PRINT IN ROW-COLUMN ORDER
subroutine print_vector_int(title,arr)
character(len=*),intent(in)  :: title
integer,intent(in)           :: arr(:)
   call print_matrix_int(title,reshape(arr,[1,shape(arr)]))
end subroutine print_vector_int

subroutine print_matrix_int(title,arr)
!@(#) print small 2d integer arrays in row-column format
character(len=*),parameter :: all='(" > ",*(g0,1x))' ! a handy format
character(len=*),intent(in)  :: title
integer,intent(in)           :: arr(:,:)
integer                      :: i
character(len=:),allocatable :: biggest

   print all
   print all, trim(title)
   biggest='           '  ! make buffer to write integer into
   ! find how many characters to use for integers
   write(biggest,'(i0)')ceiling(log10(real(maxval(abs(arr)))))+2
   ! use this format to write a row
   biggest='(" > [",*(i'//trim(biggest)//':,","))'
   ! print one row of array at a time
   do i=1,size(arr,dim=1)
      write(*,fmt=biggest,advance='no')arr(i,:)
      write(*,'(" ]")')
   enddo

end subroutine print_matrix_int

end program demo_matmul

結果

    >
    > A is
    > [  1,  3,  5 ]
    > [  2,  4,  6 ]
    >
    > B is
    > [  10,  40 ]
    > [  20,  50 ]
    > [  30,  60 ]
    >
    > C is
    > [  1,  2 ]
    >
    > D is
    > [  1,  2,  3 ]
    >
    > E is matmul(A,B)
    > [  220,  490 ]
    > [  280,  640 ]
    >
    > F is matmul(C,A)
    > [   5,  11,  17 ]
    >
    > G is matmul(A,D)
    > [  22,  28 ]
    > shape
    >
    > Cd is a vector (not a scalar)
    > [  3300 ]
    >
    > cD is a vector too
    > [  3300 ]
    >
    > CD is a matrix
    > [  3300 ]

標準#

Fortran 95

関連事項#

product(3), transpose(3)

リソース#

  • 行列積 : Wikipedia

  • 非常に大きな行列の乗算を最適化するために、ストラッセンの行列乗算アルゴリズムのウィノグラード変種が役立つ場合があります。以下を参照してください。

    "GEMMW: A portable level 3 BLAS Winograd variant of Strassen's
    matrix-matrix multiply algorithm",

    Douglas, C. C., Heroux, M., Slishman, G., and Smith, R. M.,
    Journal of Computational Physics,
    Vol. 110, No. 1, January 1994, pages 1-10.

  The numerical instabilities of Strassen's method for matrix
  multiplication requires special processing.

fortran-lang の組み込み関数の説明 (ライセンス: MIT) @urbanjost

parity#

名前#

parity(3) - [配列:縮約] .NEQV.演算による配列の縮約

概要#

    result = parity( mask [,dim] )
     logical(kind=KIND) function parity(mask, dim)

      type(logical(kind=KIND)),intent(in)        :: mask(..)
      type(integer(kind=**)),intent(in),optional :: dim

特性#

  • mask論理型の配列です。

  • dimは整数型のスカラーです。

  • 結果は、maskと同じ種類の型パラメーターを持つ論理型です。dimが表示されない場合はスカラーになります。それ以外の場合は、dimで指定された次元が削除されたmaskのランクと形状になります。

  • ** で指定された種別は、その型でサポートされている任意の種別になる可能性があります

説明#

parity(3)は、dimが存在し、1でない場合、次元dimに沿ったmaskのパリティ配列(つまり、.neqv.を使用した縮約)を計算します。それ以外の場合は、スカラーとして、mask配列全体のパリティを返します。

オプション#

  • mask

    論理型の配列である必要があります。

  • dim

    (オプション)1からnの範囲の値を持つ整数型のスカラーである必要があります。ここで、nmaskのランクに等しくなります。

結果#

結果は、maskと同じ型です。

dimがない場合、mask内のすべての要素のパリティを持つスカラーが返されます。奇数の要素が.true.の場合は.true.、それ以外の場合は.false.です。

MASKのランクが1の場合、PARITY (MASK, DIM) はPARITY (MASK) と同じです。それ以外の場合、結果は次元dimが削除されたパリティ値の配列になります。

#

サンプルプログラム

program demo_parity
implicit none
logical, parameter :: T=.true., F=.false.
logical :: x(3,4)
  ! basics
   print *, parity([T,F])
   print *, parity([T,F,F])
   print *, parity([T,F,F,T])
   print *, parity([T,F,F,T,T])
   x(1,:)=[T,T,T,T]
   x(2,:)=[T,T,T,T]
   x(3,:)=[T,T,T,T]
   print *, parity(x)
   print *, parity(x,dim=1)
   print *, parity(x,dim=2)
end program demo_parity

結果

 >  T
 >  T
 >  F
 >  T
 >  F
 >  T T T T
 >  F F F

標準#

Fortran 2008

関連事項#

  • all(3) - すべての値が真であるかどうかを判断します

  • any(3) - 論理配列内のいずれかの値が.true.であるかどうかを判断します

  • count(3) - 配列内の真の値をカウントします

  • sum(3) - 配列の要素を合計します

  • maxval(3) - 配列または行の最大値を決定します

  • minval(3) - 配列の最小値

  • product(3) - 配列要素の積

  • reduce(3) - 一般的な配列の縮約

fortran-lang の組み込み関数の説明 (ライセンス: MIT) @urbanjost

null#

名前#

null(3) - [変換関数] 解放されたポインタを返す関数

概要#

    ptr => null( [mold] )
     function null(mold)

      type(TYPE(kind=**)),pointer,optional :: mold

特性#

  • moldは、任意の状態と任意の型のポインタです。

  • 結果は、解放されたポインタまたは未割り当ての割り当て可能なエンティティです。

説明#

null(3)は、解放されたポインタを返します。

moldが存在する場合、同じ型の解放されたポインタが返されます。それ以外の場合、型はコンテキストによって決定されます。

Fortran 95では、moldはオプションです。Fortran 2003には、必須となるケースが含まれていることに注意してください。

オプション#

  • mold

    任意の状態と任意の型のポインタ。

結果#

解放されたポインタまたは未割り当ての割り当て可能なエンティティ。

#

サンプルプログラム

!program demo_null
module showit
implicit none
private
character(len=*),parameter :: g='(*(g0,1x))'
public gen
! a generic interface that only differs in the
! type of the pointer the second argument is
interface gen
 module procedure s1
 module procedure s2
end interface

contains

subroutine s1 (j, pi)
 integer j
 integer, pointer :: pi
   if(associated(pi))then
      write(*,g)'Two integers in S1:,',j,'and',pi
   else
      write(*,g)'One integer in S1:,',j
   endif
end subroutine s1

subroutine s2 (k, pr)
 integer k
 real, pointer :: pr
   if(associated(pr))then
      write(*,g)'integer and real in S2:,',k,'and',pr
   else
      write(*,g)'One integer in S2:,',k
   endif
end subroutine s2

end module showit

program demo_null
use showit, only : gen

real,target :: x = 200.0
integer,target :: i = 100

real, pointer :: real_ptr
integer, pointer :: integer_ptr

! so how do we call S1() or S2() with a disassociated pointer?

! the answer is the null() function with a mold value

! since s1() and s2() both have a first integer
! argument the NULL() pointer must be associated
! to a real or integer type via the mold option
! so the following can distinguish whether s1(1)
! or s2() is called, even though the pointers are
! not associated or defined

call gen (1, null (real_ptr) )    ! invokes s2
call gen (2, null (integer_ptr) ) ! invokes s1
real_ptr => x
integer_ptr => i
call gen (3, real_ptr ) ! invokes s2
call gen (4, integer_ptr ) ! invokes s1

end program demo_null

結果

   One integer in S2:, 1
   One integer in S1:, 2
   integer and real in S2:, 3 and 200.000000
   Two integers in S1:, 4 and 100

標準#

Fortran 95

関連事項#

associated(3)

fortran-lang の組み込み関数の説明 (ライセンス: MIT) @urbanjost

reduce#

名前#

reduce(3) - [変換関数] 配列の一般的な縮約

概要#

この関数には2つの形式があります

   result = reduce(array, operation [,mask]  [,identity]  [,ordered] )

または

   result = reduce (array, operation, dim  &
   & [,mask] [,identity] [,ordered] )
    type(TYPE(kind=KIND)) function reduce &
    & (array, operation, dim, mask, identity, ordered )

     type(TYPE(kind=KIND)),intent(in) :: array
     pure function                  :: operation
     integer,intent(in),optional    :: dim
     logical,optional               :: mask
     type(TYPE),intent(in),optional :: identity
     logical,intent(in),optional    :: ordered

特性#

  • arrayは任意の型の配列です

  • operationは、正確に2つの引数を持つ純粋関数です

    • 各引数は、スカラー、割り当て不可、非ポインター、非ポリモーフィック、非オプションで、配列と同じ型と種類です。

    • 一方の引数が非同期、ターゲット、または値属性を持っている場合、もう一方もそうである必要があります。

  • dim整数型のスカラーです

  • maskは、arrayと適合する論理型です。

  • identityは、arrayと同じ型と型パラメーターを持つスカラーです

  • orderedは論理型のスカラーです

  • 結果は、arrayと同じ型と型パラメーターです。

説明#

reduce(3)は、2項関数を繰り返し適用することにより、配列から条件付きで選択された値のリストを単一の値に縮約します。

関数型プログラミングで一般的なreduce関数は、二項演算子(2つの引数を持つ純粋関数)をすべての要素に累積的に適用します。

reduceは「高階」関数です。つまり、他の関数を引数として受け取る関数です。

reduce関数は、二項演算子(基本的な算術演算子と同様に、2つの引数を持つ関数)を受け取ります。最初に、リスト内の未使用の2つの値に適用され、アキュムレータ値を生成します。このアキュムレータ値は、関数が入力配列内の残りの選択された値すべてに再帰的に適用される際の最初の引数として使用されます。

オプション#

  • array

    任意の型および許容されるランクの配列で、値を抽出します。

  • operation

    厳密に2つの引数を持つ純粋関数である必要があります。各引数は、arrayと同じ型および型パラメーターを持つ、スカラー、割り付け不可、ポインタ不可、非多態、オプション不可のダミーデータオブジェクトである必要があります。一方の引数がASYNCHRONOUS、TARGET、またはVALUE属性を持つ場合、もう一方もその属性を持つ必要があります。結果は、非多態スカラーであり、arrayと同じ型と型パラメーターを持つ必要があります。operationは、数学的に結合的な演算を実装する必要があります。可換である必要はありません。

    注意

    operationが計算上結合的でない場合、ORDERED=.TRUE.を指定しないREDUCEは、同じ引数値であっても常に同じ結果を生成するとは限りません。これは、プロセッサが評価に結合法則を適用できるためです。

    数学的には結合的である多くの演算は、浮動小数点数に適用すると結合的でなくなります。たとえば、値を合計する順序が結果に影響を与える可能性があります。

  • dim

    整数スカラーで、1 <= dim <= n の範囲の値です。ここで、n は array のランクです。

  • mask

    (オプション) 論理型であり、array と適合している必要があります。

    存在する場合、mask の対応する要素が真である array の要素のみが operation に渡されます。まるで array が **pack(3)** でフィルタリングされたかのように扱われます。

  • identity

    array と同じ型と型パラメーターを持つスカラーである必要があります。初期シーケンスが空の場合、identify が存在する場合は、結果の値は identify になります。そうでない場合は、エラー終了が開始されます。

  • ordered

    論理スカラーである必要があります。ordered が値 .true. で存在する場合、operator 関数への呼び出しは array の最初の2つの要素から開始し、シーケンスが1つの要素になるまで行・列順に処理が続きます。これがリダクションの値になります。それ以外の場合、コンパイラは演算が可換であると自由に想定でき、リダクションを最も最適な方法で評価できます。

結果#

結果は array と同じ型および型パラメーターを持ちます。dim が表示されない場合はスカラーです。

dim が存在する場合、これはリダクションを実行する1つの次元を示し、結果の配列は入力配列と比較してランクが1つ減少します。

#

次の例はすべて、2つの実数引数の積を返す関数 MY_MULT を使用しています。

   program demo_reduce
   implicit none
   character(len=*),parameter :: f='("[",*(g0,",",1x),"]")'
   integer,allocatable :: arr(:), b(:,:)

   ! Basic usage:
      ! the product of the elements of an array
      arr=[1, 2, 3, 4 ]
      write(*,*) arr
      write(*,*) 'product=', reduce(arr, my_mult)
      write(*,*) 'sum=', reduce(arr, my_sum)

   ! Examples of masking:
      ! the product of only the positive elements of an array
      arr=[1, -1, 2, -2, 3, -3 ]
      write(*,*)'positive value product=',reduce(arr, my_mult, mask=arr>0)
   ! sum values ignoring negative values
      write(*,*)'sum positive values=',reduce(arr, my_sum, mask=arr>0)

   ! a single-valued array returns the single value as the
   ! calls to the operator stop when only one element remains
      arr=[ 1234 ]
      write(*,*)'single value sum',reduce(arr, my_sum )
      write(*,*)'single value product',reduce(arr, my_mult )

   ! Example of operations along a dimension:
   !  If B is the array   1 3 5
   !                      2 4 6
      b=reshape([1,2,3,4,5,6],[2,3])
      write(*,f) REDUCE(B, MY_MULT),'should be [720]'
      write(*,f) REDUCE(B, MY_MULT, DIM=1),'should be [2,12,30]'
      write(*,f) REDUCE(B, MY_MULT, DIM=2),'should be [15, 48]'

   contains

   pure function my_mult(a,b) result(c)
   integer,intent(in) :: a, b
   integer            :: c
      c=a*b
   end function my_mult

   pure function my_sum(a,b) result(c)
   integer,intent(in) :: a, b
   integer            :: c
      c=a+b
   end function my_sum

   end program demo_reduce

結果

     >  1 2 3 4
     >  product= 24
     >  sum=     10
     >  positive value sum= 6
     >  sum positive values= 6
     >  single value sum     1234
     >  single value product 1234
     > [720, should be [720],
     > [2, 12, 30, should be [2,12,30],
     > [15, 48, should be [15, 48],

標準#

Fortran 2018

参照#

リソース#

fortran-lang の組み込み関数の説明 (ライセンス: MIT) @urbanjost