行列積、ドット積、および配列シフト#
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_a と vector_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
関連項目#
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
関連事項#
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は、数値型(integer、real、またはcomplex)または論理型のランク1または2の配列です。
matrix_bは、数値型(integer、real、または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_aとmatrix_bは異なる数値型である可能性があることに注意してください。
結果#
数値引数#
matrix_aとmatrix_bが数値型の場合、結果はmatrix_aとmatrix_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_aとmatrix_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
関連事項#
リソース#
非常に大きな行列の乗算を最適化するために、ストラッセンの行列乗算アルゴリズムのウィノグラード変種が役立つ場合があります。以下を参照してください。
"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の範囲の値を持つ整数型のスカラーである必要があります。ここで、nはmaskのランクに等しくなります。
結果#
結果は、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
関連事項#
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