サーチ…
基本表記
任意の種類は、 ディメンション属性のいずれかを使用してアレイとして、または単に直接示すことで宣言することができるdimension
アレイの(単数または複数)
! One dimensional array with 4 elements
integer, dimension(4) :: foo
! Two dimensional array with 4 rows and 2 columns
real, dimension(4, 2) :: bar
! Three dimensional array
type(mytype), dimension(6, 7, 8) :: myarray
! Same as above without using the dimension keyword
integer :: foo2(4)
real :: bar2(4, 2)
type(mytype) :: myarray2(6, 7, 8)
多次元配列を宣言する後者の方法では、次のように、同じタイプの異なるランク/ディメンション配列を1行に宣言することができます
real :: pencil(5), plate(3,-2:4), cuboid(0:3,-10:5,6)
最大ランク(ディメンション数)は、Fortran 2008標準では15であり、以前は7でした。
列優先順でFortranの店舗アレイ。すなわち、 bar
の要素は次のようにメモリに格納されます。
bar(1, 1), bar(2, 1), bar(3, 1), bar(4, 1), bar(1, 2), bar(2, 2), ...
Fortranでは、デフォルトで配列の番号付けが1から始まり、Cとは異なり0から始まります 。実際、Fortranでは、各ディメンションの上限と下限を明示的に指定できます。
integer, dimension(7:12, -3:-1) :: geese
これは、最初の要素がgeese(7, -3)
であるシェイプ(6, 3)
6,3)の配列を宣言します。
2つ(またはそれ以上)の次元に沿った下限および上限は、組み込み関数ubound
およびlbound
によってアクセスできます。実際にlbound(geese,2)
は-3
を返す一方、 ubound(geese,1)
は12
を返します。
配列のサイズは、組み込み関数のsize
によってアクセスできます。たとえば、 size(geese, dim = 1)
は最初の次元のサイズ6を返します。
割り当て可能な配列
配列は、 割り当て可能な属性を持つことができます:
! One dimensional allocatable array
integer, dimension(:), allocatable :: foo
! Two dimensional allocatable array
real, dimension(:,:), allocatable :: bar
これは変数を宣言しますが、変数にはスペースを割り当てません。
! We can specify the bounds as usual
allocate(foo(3:5))
! It is an error to allocate an array twice
! so check it has not been allocated first
if (.not. allocated(foo)) then
allocate(bar(10, 2))
end if
いったん変数が不要になれば、 割り当てを解除することができます :
deallocate(foo)
何らかの理由でallocate
ステートメントが失敗した場合、プログラムは停止します。ステータスがstat
キーワードでチェックされている場合、これを防ぐことができます:
real, dimension(:), allocatable :: geese
integer :: status
allocate(geese(17), stat=status)
if (stat /= 0) then
print*, "Something went wrong trying to allocate 'geese'"
stop 1
end if
deallocate
ステートメントにもstat
キーワードがあります:
deallocate (geese, stat=status)
status
は、割り当てまたは解放が成功した場合に値が0である整数変数です。
配列コンストラクタ
ランク1の配列値は、 配列コンストラクタを使用して、構文
(/ ... /)
[ ... ]
フォーム[...]
はFortran 2003で導入されました。一般に、特に複雑な表現では、読みやすくすると考えられています。このフォームは、この例では排他的に使用されます。
配列コンストラクターでフィーチャーされる値は、スカラー値、配列値、または暗黙の実行ループです。
構築された配列の型と型のパラメータは、配列のコンストラクタの値の型と型のパラメータと一致します
[1, 2, 3] ! A rank-1 length-3 array of default integer type
[1., 2., 3.] ! A rank-1 length-3 array of default real type
["A", "B"] ! A rank-1 length-2 array of default character type
integer, parameter :: A = [2, 4]
[1, A, 3] ! A rank-1 length-4 array of default integer type, with A's elements
integer i
[1, (i, i=2, 5), 6] ! A rank-1 length-6 array of default integer type with an implied-do
上記の形式では、与えられたすべての値は同じ型および型パラメータでなければなりません。ミキシングタイプまたはタイプパラメータは使用できません。次の例は有効ではありません
[1, 2.] ! INVALID: Mixing integer and default real
[1e0, 2d0] ! INVALID: Mixing default real and double precision
[1., 2._dp] ! INVALID: Allowed only if kind `dp` corresponds to default real
["Hello", "Frederick"] ! INVALID: Different length parameters
異なる型を使用して配列を構築するには、配列の型指定を与えなければならない
[integer :: 1, 2., 3d0] ! A default integer array
[real(dp) :: 1, 2, 3._sp] ! A real(dp) array
[character(len=9) :: "Hello", "Frederick"] ! A length-2 array of length-9 characters
この後者の文字配列の形式は、スペースの埋め込みを避けるために特に便利です
["Hello ", "Frederick"] ! A length-2 array of length-9 characters
定数という名前の配列のサイズは、その値を設定するために使用される配列コンストラクタによって暗示される場合があります
integer, parameter :: ids(*) = [1, 2, 3, 4]
長さパラメータ型の場合、長さパラメータを仮定することができる
character(len=*), parameter :: names(*) = [character(3) :: "Me", "You", "Her"]
型指定は、長さゼロの配列の構築にも必要です。から
[ ] ! Not a valid array constructor
タイプとタイプのパラメーターは、存在しない値セットからは判別できません。ゼロ長のデフォルト整数配列を作成するには:
[integer :: ]
配列コンストラクタは、rank-1配列のみを構築します。名前付き定数の値の設定など、時には、上位の配列も式に必要です。 reshape
れたランク1の配列を使用して、より高いランクの配列をreshape
の結果から取得できます
integer, parameter :: multi_rank_ids(2,2) = RESHAPE([1,2,3,4], shape=[2,2])
配列コンストラクタでは、値のリスト内の任意の配列を持つ要素の順序の配列の値は、個々の要素が配列要素の順序で与えられているかのようになります。したがって、先の例
integer, parameter :: A = [2, 4]
[1, A, 3] ! A rank-1 length-4 array of default integer type, with A's elements
は
[1, 2, 4, 3] ! With the array written out in array element order
一般に、コンストラクタの値は、ネストされた配列コンストラクタを含む任意の式である可能性があります。そのような配列コンストラクタが定数や仕様式などの特定の条件を満たすためには、制約が構成要素の値に適用されます。
配列コンストラクタはないが、特定の配列の値はまた、好都合に使用して作成することができるspread
組み込み関数を。例えば
[(0, i=1,10)] ! An array with 10 default integers each of value 0
関数参照の結果でもある
SPREAD(0, 1, 10)
配列の性質の指定:ランクとシェイプ
オブジェクトのdimension
属性は、そのオブジェクトが配列であることを示します。 Fortran 2008では、5つの配列の性質があります。1
- 明示的な形
- 想定形状
- 想定サイズ
- 遅延形状
- 暗黙の形状
3つのランク1の配列を取る2
integer a, b, c
dimension(5) a ! Explicit shape (default lower bound 1), extent 5
dimension(:) b ! Assumed or deferred shape
dimension(*) c ! Assumed size or implied shape array
これらを用いて、配列の性質を完全に決定するためにさらなるコンテキストが必要であることが分かる。
明示的な形状
明示的なシェイプ配列は、常にその宣言の形です。配列がサブプログラムまたはblock
構造に対してローカルとして宣言されていない限り、シェイプを定義する境界は定数式でなければなりません。他の場合では、明示的なシェイプ配列は、サブプログラムまたはblock
呼び出しごとに異なる可能性のあるエクステントを使用する自動オブジェクトです。
subroutine sub(n)
integer, intent(in) :: n
integer a(5) ! A local explicit shape array with constant bound
integer b(n) ! A local explicit shape array, automatic object
end subroutine
仮定された形状
想定される形状配列は、 allocatable
またはpointer
属性のない仮引数です。そのような配列は、それが関連付けられている実際の引数から形状をとります。
integer a(5), b(10)
call sub(a) ! In this call the dummy argument is like x(5)
call sub(b) ! In this call the dummy argument is like x(10)
contains
subroutine sub(x)
integer x(:) ! Assumed shape dummy argument
end subroutine sub
end
仮引数がシェイプを仮定している場合、プロシージャを参照するスコープは、そのプロシージャで使用可能な明示的なインタフェースを持っていなければなりません。
推定サイズ
想定されるサイズの配列は、実際の引数から想定されるサイズを持つ仮引数です。
subroutine sub(x)
integer x(*) ! Assumed size array
end subroutine
仮定されたサイズ配列は、仮定された形状配列とはまったく異なった挙動を示し、これらの相違点は別の場所で文書化されている。
遅れた形状
遅延シェイプ配列は、 allocatable
属性またはpointer
属性を持つ配列です。そのような配列の形状は、その割り当てまたはポインタの割り当てによって決定されます。
integer, allocatable :: a(:)
integer, pointer :: b(:)
暗示された形状
暗黙の形状配列は、その値を確立するために使用された式から形状をとる名前付き定数です
integer, parameter :: a(*) = [1,2,3,4]
仮引数に対するこれらの配列宣言の意味は、他の場所で文書化されています。
1 Fortran 2008を拡張した技術仕様には、6番目の配列特性が追加されています。これはここでは扱いません。
2これらは等価的に次のように書くことができます。
integer, dimension(5) :: a
integer, dimension(:) :: b
integer, dimension(*) :: c
または
integer a(5)
integer b(:)
integer c(*)
全配列、配列要素、配列セクション
として宣言された配列を考えてみましょう
real x(10)
次に、興味のある3つの側面があります。
- 配列全体
x
; -
x(1)
ような配列要素。 -
x(2:6)
ような配列セクション。
配列全体
ほとんどの場合、配列x
は配列のすべての要素を単一のエンティティとして参照します。 print *, SUM(x)
、 print *, SIZE(x)
、 x=1
などの実行可能文に現れることがあります。
配列全体は、明示的に整形されていない配列(上記のx
など)を参照することがあります:
function f(y)
real, intent(out) :: y(:)
real, allocatable :: z(:)
y = 1. ! Intrinsic assignment for the whole array
z = [1., 2.,] ! Intrinsic assignment for the whole array, invoking allocation
end function
想定されるサイズの配列は配列全体として表示されることもありますが、限られた状況でしか表示されません(別の場所で文書化されます)。
配列要素
配列要素は、配列全体の位置を示す、配列の各ランクごとに1つの整数インデックスを与えると呼ばれます。
real x(5,2)
x(1,1) = 0.2
x(2,4) = 0.3
配列要素はスカラです。
配列セクション
配列セクションは、コロンを含む構文を使用して、配列全体のいくつかの要素(おそらくは1つだけ)への参照です。
real x(5,2)
x(:,1) = 0. ! Referring to x(1,1), x(2,1), x(3,1), x(4,1) and x(5,1)
x(2,:) = 0. ! Referring to x(2,1), x(2,2)
x(2:4,1) = 0. ! Referring to x(2,1), x(3,1) and x(4,1)
x(2:3,1:2) = 0. ! Referring to x(2,1), x(3,1), x(2,2) and x(3,2)
x(1:1,1) = 0. ! Referring to x(1,1)
x([1,3,5],2) = 0. ! Referring to x(1,2), x(3,2) and x(5,2)
上の最後の書式は、 ベクトルの添え字を使用しています 。これは、他の配列セクションを超えていくつかの制限があります。
1つの要素だけが参照されている場合でも、各配列セクション自体が配列です。つまり、 x(1:1,1)
はランク1の配列であり、 x(1:1,1:1)
はランク2の配列です。
配列セクションには一般的に、配列全体の属性はありません。特に、どこで
real, allocatable :: x(:)
x = [1,2,3] ! x is allocated as part of the assignment
x = [1,2,3,4] ! x is dealloacted then allocated to a new shape in the assignment
割り当て
x(:) = [1,2,3,4,5] ! This is bad when x isn't the same shape as the right-hand side
許可されていない: x(:)
、すべての要素を持つアレイ部がx
、割付け配列ではありません。
x(:) = [5,6,7,8]
x
が右辺の形であれば問題ありません。
配列の配列コンポーネント
type t
real y(5)
end type t
type(t) x(2)
より複雑な設定では、配列全体、配列要素、配列セクションを参照することもあります。
上記から、 x
は配列全体です。我々はまた持っている
x(1)%y ! A whole array
x(1)%y(1) ! An array element
x%y(1) ! An array section
x(1)%y(:) ! An array section
x([1,2]%y(1) ! An array section
x(1)%y(1:1) ! An array section
そのような場合には、参照の1つ以上の部分が階数1の配列で構成されることは許されません。たとえば、次のようなものは許可されません
x%y ! Both the x and y parts are arrays
x(1:1)%y(1:1) ! Recall that each part is still an array section
配列演算
その計算上の目標のために、配列に対する数学演算は、Fortranでは簡単です。
足し算と引き算
同じ形状とサイズの配列に対する演算は、行列代数と非常によく似ています。ループですべてのインデックスを実行する代わりに、加算(および減算)を書くことができます。
real, dimension(2,3) :: A, B, C
real, dimension(5,6,3) :: D
A = 3. ! Assigning single value to the whole array
B = 5. ! Equivalent writing for assignment
C = A + B ! All elements of C now have value 8.
D = A + B ! Compiler will raise an error. The shapes and dimensions are not the same
スライスからの配列も有効です:
integer :: i, j
real, dimension(3,2) :: Mat = 0.
real, dimension(3) :: Vec1 = 0., Vec2 = 0., Vec3 = 0.
i = 0
j = 0
do i = 1,3
do j = 1,2
Mat(i,j) = i+j
enddo
enddo
Vec1 = Mat(:,1)
Vec2 = Mat(:,2)
Vec3 = Mat(1:2,1) + Mat(2:3,2)
関数
同様に、ほとんどの組み込み関数は、コンポーネント単位の操作を前提として暗黙的に使用できます(これは体系的ではありません)。
real, dimension(2) :: A, B
A(1) = 6
A(2) = 44 ! Random values
B = sin(A) ! Identical to B(1) = sin(6), B(2) = sin(44).
乗算と除算
製品と部門に注意を払う必要があります。 *
と/
記号を使用した組み込み演算は要素単位です:
real, dimension(2) :: A, B, C
A(1) = 2
A(2) = 4
B(1) = 1
B(2) = 3
C = A*B ! Returns C(1) = 2*1 and C(2) = 4*3
これは行列演算と誤ってはいけません(下記参照)。
行列操作
行列演算は固有の手続きである。たとえば、前のセクションの配列の行列積は次のように書かれます。
real, dimension(2,1) :: A, B
real, dimension(1,1) :: C
A(1) = 2
A(2) = 4
B(1) = 1
B(2) = 3
C = matmul(transpose(A),B) ! Returns the scalar product of vectors A and B
複雑な操作では、一時配列を作成して関数をカプセル化できます。一部のコンパイラやコンパイルオプションでは許可されていますが、これは推奨されません。例えば、行列転置を含む製品は、次のように書くことができる。
real, dimension(3,3) :: A, B, C
A(:) = 4
B(:) = 5
C = matmul(transpose(A),matmul(B,matmul(A,transpose(B)))) ! Equivalent to A^t.B.A.B^T
高度な配列セクション:添字三つ組とベクトル添え字
別の例で述べたように、配列セクションと呼ばれる配列の要素のサブセットを参照することができます。その例から、
real x(10)
x(:) = 0.
x(2:6) = 1.
x(3:4) = [3., 5.]
ただし、配列セクションはこれより一般的かもしれません。それらは、添字三つ組またはベクトル添え字の形を取ることができる。
下付き文字のトリプレット
下付き文字のトリプルは、 [bound1]:[bound2][:stride]
という形式をとります。例えば
real x(10)
x(1:10) = ... ! Elements x(1), x(2), ..., x(10)
x(1:) = ... ! The omitted second bound is equivalent to the upper, same as above
x(:10) = ... ! The omitted first bound is equivalent to the lower, same as above
x(1:6:2) = ... ! Elements x(1), x(3), x(5)
x(5:1) = ... ! No elements: the lower bound is greater than the upper
x(5:1:-1) = ... ! Elements x(5), x(4), x(3), x(2), x(1)
x(::3) = ... ! Elements x(1), x(4), x(7), x(10), assuming omitted bounds
x(::-3) = ... ! No elements: the bounds are assumed with the first the lower, negative stride
ストライド(ゼロであってはならない)が指定されると、要素のシーケンスは指定された最初の境界から始まります。ストライドが正の場合(負の値の場合)、シーケンスに続く選択された要素は、第2の境界よりも大きくない(より小さい)最後の要素が取られるまで、ストライドによって増分(減分)されます。ストライドを省略すると、ストライドは1つとして扱われます。
最初の境界が2番目の境界より大きく、ストライドが正の場合、要素は指定されません。最初の境界が2番目の境界よりも小さく、ストライドが負である場合、要素は指定されません。
ことに留意すべきであるx(10:1:-1)
同じではないx(1:10:1)
の各要素にもかかわらず、 x
いずれの場合にも現れます。
ベクトル添え字
ベクトル添字は、ランク1の整数配列です。これは、配列の値に対応する要素のシーケンスを指定します。
real x(10)
integer i
x([1,6,4]) = ... ! Elements x(1), x(6), x(4)
x([(i,i=2,4)]) = ... ! Elements x(2), x(3) and x(4)
print*, x([2,5,2]) ! Elements x(2), x(5) and x(2)
ベクトル添え字を持つ配列セクションは、使用方法が制限されています:
- プロシージャーで定義された仮引き数に関連する引き数ではない可能性があります。
- それはポインタ代入文ではターゲットではないかもしれません。
- データ転送ステートメントの内部ファイルではない可能性があります。
さらに、同じ要素が2回選択されたときに、その定義を含むステートメントにそのような配列セクションが現れないことがあります。上から:
print*, x([2,5,2]) ! Elements x(2), x(5) and x(2) are printed
x([2,5,2]) = 1. ! Not permitted: x(2) appears twice in this definition
上位の配列セクション
real x(5,2)
print*, x(::2,2:1:-1) ! Elements x(1,2), x(3,2), x(5,2), x(1,1), x(3,1), x(5,1)