WHERE 構造体は、配列式および配列割り当ての計算をマスクします。これは論理配列式の値に応じて実行されます。
.--------------------------. V | >>-WHERE_construct_statement----+----------------------+-+------> '-where_body_construct-' .----------------------------. .---------------------. V | V | >----+------------------------+-+----+-----------------+-+------> '-masked_ELSEWHERE_block-' '-ELSEWHERE_block-' >--END_WHERE_statement----------------------------------------->< |
>>-+-where_assignment_statement-+------------------------------>< | (1) | +-WHERE_statement------------+ | (2) | '-WHERE_construct------------' 注:
|
+---------------------------------Fortran 95---------------------------------+
>>-masked_ELSEWHERE_statement--+----------------------+-------->< '-where_body_construct-' |
+------------------------------Fortran 95 の終り------------------------------+
>>-ELSEWHERE_statement--+----------------------+--------------->< '-where_body_construct-' |
規則:
+---------------------------------Fortran 95---------------------------------+
+------------------------------Fortran 95 の終り------------------------------+
マスクされた配列割り当ての解釈方法を理解するには、 制御マスク (mc) および 保留制御マスク (mp) の概念について理解する必要があります。
またはマスクされた ELSEWHERE ステートメント
によって定義されていない配列エレメント上の同じネスト・レベルで、次のマスクされた割り当てステートメントに情報を提供します。
以下では、コンパイラーが WHERE、WHERE 構造体、
マスクされた ELSEWHERE
、
ELSEWHERE、または END WHERE ステートメント内のステートメントを解釈する方法を説明しています。ここでは mc や mp、およびこれ以外のステートメントの動作に与える影響について、発生の順番に説明しています。
+---------------------------------Fortran 95---------------------------------+
+------------------------------Fortran 95 の終り------------------------------+
+---------------------------------Fortran 95---------------------------------+
+------------------------------Fortran 95 の終り------------------------------+
+---------------------------------Fortran 95---------------------------------+
以下のことが起きます。
+------------------------------Fortran 95 の終り------------------------------+
以下のことが起きます。
コンパイラーが END WHERE ステートメントを実行した後、mc と mp は、対応する WHERE 構造体ステートメントの実行前に持っていた値を持ちます。
コンパイラーは、mc の真の値に対応する expr の値を、対応する variable のエレメントに割り当てます。
非エレメント型関数参照が where_assignment_statement 内の expr または variable、または mask_expr にある場合、コンパイラーはマスクされた制御なしで関数を評価します。つまり、完全に関数の引き数式のすべてを評価し、それによって完全に関数を評価します。結果が配列で、参照が非エレメント型関数の引き数リストの範囲内にない場合、expr、variable、または mask_expr の計算に使用するために mc 内の真の値に対応するエレメントが選択されます。
エレメント型の組み込み演算または関数参照が where_assignment_statement または mask_expr の expr または variable で発生し、非エレメント型関数参照の引き数リストの範囲内にない場合、mc 内の真の値に対応するエレメントに対してのみ、演算が実行されるか、あるいは関数が計算されます。
配列コンストラクターが where_assignment_statement または mask_expr にある場合、コンパイラーは配列コンストラクターを、マスクされた制御なしで評価し、それから where_assignment_statement を実行するか、または mask_expr を評価します。
WHERE ステートメントの mask_expr 内の関数参照を実行することによって、where_assignment_statement 内のエンティティーに影響を与えることができます。 END WHERE を実行しても、影響はありません。
以下の例は、制御マスクが更新される方法を示しています。この例で、mask1、mask2、mask3、および mask4 は適合論理配列で、mc は制御マスクで、mp は保留制御マスクです。コンパイラーはそれぞれのマスク式を一度評価します。
サンプル・コード (注釈内にステートメント番号を示しています)
WHERE (mask1) ! W1 * WHERE (mask2) ! W2 * ... ! W3 * ELSEWHERE (mask3) ! W4 * ... ! W5 * END WHERE ! W6 * ELSEWHERE (mask4) ! W7 * ... ! W8 * ELSEWHERE ! W9 ... ! W10 END WHERE ! W11
以下に示すとおり、コンパイラーは制御および保留制御マスクを、それぞれのステートメントを実行するごとに設定します。
+---------------------------------Fortran 95---------------------------------+
+------------------------------Fortran 95 の終り------------------------------+
Statement W7
mc = .NOT. mask1
mp = (.NOT. mask1) .AND. (.NOT.
mask4)
mc = (.NOT. mask1) .AND. mask4
Statement W9
mc = (.NOT. mask1) .AND. (.NOT.
mask4)
Statement W11
mc = 0
mp = 0
コンパイラーは、ステートメント W2、W4、W7、および W9 によって設定された制御マスクの値を、それぞれ where_assignment_statement の W3、W5、W8、および W10 を実行するときに使用します。
マイグレーションのためのヒント: 配列の論理計算を単純化します。 FORTRAN 77 ソース INTEGER A(10,10),B(10,10) Fortran 90 または Fortran 95 ソース: INTEGER A(10,10),B(10,10) |
REAL, DIMENSION(10) :: A,B,C,D WHERE (A>0.0) A = LOG(A) ! Only the positive elements of A ! are used in the LOG calculation. B = A ! The mask uses the original array A ! instead of the new array A. C = A / SUM(LOG(A)) ! A is evaluated by LOG, but ! the resulting array is an ! argument to a non-elemental ! function. All elements in A will ! be used in evaluating SUM. END WHERE WHERE (D>0.0) C = CSHIFT(A, 1) ! CSHIFT applies to all elements in array A, ! and the array element values of D determine ! which CSHIFT expression determines the ! corresponding element values of C. ELSEWHERE C = CSHIFT(A, 2) END WHERE END
+---------------------------------Fortran 95---------------------------------+
以下の例は、WHERE 構造体ステートメント内およびマスクされた ELSEWHERE mask_expr 内の配列コンストラクターを示しています。
CALL SUB((/ 0, -4, 3, 6, 11, -2, 7, 14 /)) CONTAINS SUBROUTINE SUB(ARR) INTEGER ARR(:) INTEGER N N = SIZE(ARR) ! Data in array ARR at this point: ! ! A = | 0 -4 3 6 11 -2 7 14 | WHERE (ARR < 0) ARR = 0 ELSEWHERE (ARR < ARR((/(N-I, I=0, N-1)/))) ARR = 2 END WHERE ! Data in array ARR at this point: ! ! A = | 2 0 3 2 11 0 7 14 | END SUBROUTINE END
以下の例は、ネストされた WHERE 構造体ステートメントおよびマスクされた ELSEWHERE ステートメントに where_construct_name を指定したものを示しています。
INTEGER :: A(10, 10), B(10, 10) ... OUTERWHERE: WHERE (A < 10) INNERWHERE: WHERE (A < 0) B = 0 ELSEWHERE (A < 5) INNERWHERE B = 5 ELSEWHERE INNERWHERE B = 10 END WHERE INNERWHERE ELSEWHERE OUTERWHERE B = A END WHERE OUTERWHERE ...
+------------------------------Fortran 95 の終り------------------------------+