Interpreting masked array assignments
- The mc is
an array of type logical whose value determines which elements of
an array in a where_assignment_statement will
be defined. This value is determined by the execution of one of the
following:
- a WHERE statement
- a WHERE construct statement
- an ELSEWHERE statement
- a masked ELSEWHERE statement
- an END WHERE statement
- The mp is a logical array that provides information to the next masked assignment statement at the same nesting level on the array elements not defined by the current WHERE statement, WHERE construct statement, or masked ELSEWHERE statement.
- WHERE statement
- If the WHERE statement is nested in
a WHERE construct, the following occurs:
- mc becomes mc .AND. mask_expr.
- After the compiler executes the WHERE statement, mc has the value it had prior to the execution of the WHERE statement.
- Otherwise, mc becomes the mask_expr.
- If the WHERE statement is nested in
a WHERE construct, the following occurs:
- WHERE construct
- If the WHERE construct is nested in
another WHERE construct, the following occurs:
- mp becomes mc .AND. (.NOT. mask_expr).
- mc becomes mc .AND. mask_expr.
- Otherwise:
- The compiler evaluates the mask_expr, and assigns mc the value of that mask_expr.
- mp becomes .NOT. mask_expr.
- If the WHERE construct is nested in
another WHERE construct, the following occurs:
- Masked ELSEWHERE statement The following occurs:
- mc becomes mp.
- mp becomes mc .AND. (.NOT. mask_expr).
- mc becomes mc .AND. mask_expr.
- ELSEWHERE statement The following occurs:
- mc becomes mp. No new mp value is established.
- END WHERE statement
After the compiler executes an END WHERE statement, mc and mp have the values they had prior to the execution of the corresponding WHERE construct statement.
- where_assignment_statement
The compiler assigns the values of the expr that correspond to the true values of mc to the corresponding elements of the variable.
If a non-elemental function reference occurs in the expr or variable of a where_assignment_statement or in a mask_expr, the compiler evaluates the function without any masked control; that is, it fully evaluates all of the function's argument expressions and then it fully evaluates the function. If the result is an array and the reference is not within the argument list of a non-elemental function, the compiler selects elements corresponding to true values in mc for use in evaluating the expr, variable, or mask_expr.
If an elemental intrinsic operation or function reference occurs in the expr or variable of a where_assignment_statement or in a mask_expr, and is not within the argument list of a non-elemental function reference, the compiler performs the operation or evaluates the function only for the elements corresponding to true values in mc.
If an array constructor appears in a where_assignment_statement or in a mask_expr, the compiler evaluates the array constructor without any masked control and then executes the where_assignment_statement or evaluates the mask_expr.
The execution of a function reference in the mask_expr of a WHERE statement is allowed to affect entities in the where_assignment_statement. Execution of an END WHERE has no effect.
The following example shows how control masks are updated. In this example, mask1, mask2, mask3, and mask4 are conformable logical arrays, mc is the control mask, and mp is the pending control mask. The compiler evaluates each mask expression once.
WHERE (mask1) ! W1
WHERE (mask2) ! W2
... ! W3
ELSEWHERE (mask3) ! W4
... ! W5
END WHERE ! W6
ELSEWHERE (mask4) ! W7
... ! W8
ELSEWHERE ! W9
... ! W10
END WHERE ! W11
The compiler sets control and pending control masks as it executes each statement, as shown below:
Statement W1
mc = mask1
mp = .NOT. mask1
Statement W2
mp = mask1 .AND. (.NOT. mask2)
mc = mask1 .AND. mask2
Statement W4
mc = mask1 .AND. (.NOT. mask2)
mp = mask1 .AND. (.NOT. mask2)
.AND. (.NOT. mask3)
mc = mask1 .AND. (.NOT. mask2)
.AND. mask3
Statement W6
mc = mask1
mp = .NOT. mask1
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
Migration Tip:
Simplify logical evaluation of arrays
INTEGER A(10,10),B(10,10)
⋮
DO I=1,10
DO J=1,10
IF (A(I,J).LT.B(I,J)) A(I,J)=B(I,J)
END DO
END DO
END
INTEGER A(10,10),B(10,10)
⋮
WHERE (A.LT.B) A=B
END
Examples
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
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
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
...