The **WHERE** construct masks the evaluation of expressions and
assignments of values in array assignment statements. It does this
according to the value of a logical array expression.

.--------------------------. .----------------------------. .---------------------. V | V | V | >>- |

`WHERE_construct_statement`- See WHERE for syntax details.

`where_body_construct`-

>>-+-

*where_assignment_statement*-+------------------------------>< | (1) | +-*WHERE_statement*------------+ | (2) | '-*WHERE_construct*------------'

**Notes:**- Fortran 95 variable

- Fortran 95 variable

- Fortran 95 variable

`where_assignment_statement`- Is an
`assignment_statement`.

+---------------------------------Fortran 95---------------------------------+

`masked_ELSEWHERE_block`-

>>-

*masked_ELSEWHERE_statement*--+----------------------+-------->< '-*where_body_construct*-'

`masked_ELSEWHERE_statement`- Is an
**ELSEWHERE**statement that specifies a`mask_expr`. See ELSEWHERE for syntax details.

+-----------------------------End of Fortran 95------------------------------+

`ELSEWHERE_block`-

>>-

*ELSEWHERE_statement*--+----------------------+--------------->< '-*where_body_construct*-'

`ELSEWHERE_statement`- Is an
**ELSEWHERE**statement that does not specify a`mask_expr`. See ELSEWHERE for syntax details.

`END_WHERE_statement`- See END (Construct) for syntax details.

Rules:

`mask_expr`is a logical array expression.- In each
`where_assignment_statement`, the`mask_expr`and the`variable`being defined must be arrays of the same shape. - A statement that is part of a
`where_body_construct`must not be a branch target statement. Also,**ELSEWHERE**, masked**ELSEWHERE**, and**END WHERE**statements must not be branch target statements.**+---------------------------------Fortran 95---------------------------------+**

- A
`where_assignment_statement`that is a defined assignment must be an elemental defined assignment. - The
`mask_expr`on the**WHERE**construct statement and all corresponding masked**ELSEWHERE**statements must have the same shape. The`mask_expr`on a nested**WHERE**statement or nested**WHERE**construct statement must have the same shape as the`mask_expr`on the**WHERE**construct statement of the construct in which it is nested. - If a construct name appears on a
**WHERE**construct statement, it must also appear on the corresponding**END WHERE**statement. A construct name is optional on the masked**ELSEWHERE**and**ELSEWHERE**statements in the**WHERE**construct.**+-----------------------------End of Fortran 95------------------------------+**

To understand how to interpret masked array assignments, you need to
understand the concepts of a `control mask` (`m`_{c}) and a `pending control mask`
(`m`_{p}):

- The
`m`_{c}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 value of

`m`_{c}is cumulative; the compiler determines the value using the mask expressions of surrounding**WHERE**statements and the current mask expression. Subsequent changes to the value of entities in a`mask_expr`have no effect on the value of`m`_{c}. The compiler evaluates the`mask_expr`only once for each**WHERE**statement,**WHERE**construct statement, or masked**ELSEWHERE**statement. - a
- The
`m`_{p}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.

The following describes how the compiler interprets statements in a
**WHERE**, **WHERE** construct,
masked **ELSEWHERE**
, **ELSEWHERE**, or **END WHERE** statement. It describes the
effect on `m`_{c} and `m`_{p} and any further behavior of the statements, in order of
occurrence.

**WHERE**statement**+---------------------------------Fortran 95---------------------------------+**- If the
**WHERE**statement is nested in a**WHERE**construct, the following occurs:`m`_{c}becomes`m`_{c}**.AND.**`mask_expr`.- After the compiler executes the
**WHERE**statement,`m`_{c}has the value it had prior to the execution of the**WHERE**statement.

**+-----------------------------End of Fortran 95------------------------------+** - Otherwise,
`m`_{c}becomes the`mask_expr`.

+---------------------------------Fortran 95---------------------------------+

`m`_{p}becomes`m`_{c}**.AND.**(**.NOT.**`mask_expr`).`m`_{c}becomes`m`_{c}**.AND.**`mask_expr`.

+-----------------------------End of Fortran 95------------------------------+

- The compiler evaluates the
`mask_expr`, and assigns`m`_{c}the value of that`mask_expr`. `m`_{p}becomes**.NOT.**`mask_expr`.

+---------------------------------Fortran 95---------------------------------+

The following occurs:

`m`_{c}becomes`m`_{p}.`m`_{p}becomes`m`_{c}**.AND.**(**.NOT.**`mask_expr`).`m`_{c}becomes`m`_{c}**.AND.**`mask_expr`.

+-----------------------------End of Fortran 95------------------------------+

The following occurs:

`m`_{c}becomes`m`_{p}. No new`m`_{p}value is established.

After the compiler executes an **END WHERE** statement, `m`_{c} and `m`_{p} have the values they had prior to the execution of the
corresponding **WHERE** construct statement.

The compiler assigns the values of the `expr` that correspond to the
true values of `m`_{c} 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 `m`_{c} 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
`m`_{c}.

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, `m`_{c} is the control mask, and `m`_{p} is the pending control mask. The compiler evaluates each
mask expression once.

Sample code (with statement numbers shown in the comments):

WHERE (mask1) ! W1*WHERE (mask2) ! W2*... ! W3*ELSEWHERE (mask3) ! W4*... ! W5*END WHERE ! W6*ELSEWHERE (mask4) ! W7*... ! W8*ELSEWHERE ! W9 ... ! W10 END WHERE ! W11

**Note:*******Fortran 95

The compiler sets control and pending control masks as it executes each statement, as shown below:

+---------------------------------Fortran 95---------------------------------+

.AND. (.NOT. mask3)

.AND. mask3

+-----------------------------End of Fortran 95------------------------------+

`Statement W7`

`m`_{c} `= .NOT. mask1`

`m`_{p} `= (.NOT. mask1) .AND. (.NOT.
mask4)`

mask4)

The compiler uses the values of the control masks set by statements
`W2`, `W4`, `W7`, and `W9` when it executes the
respective `where_assignment_statement`s `W3`, `W5`,
`W8`, and `W10`.

Simplify logical evaluation of arrays FORTRAN 77 source: INTEGER A(10,10),B(10,10) Fortran 90 or Fortran 95 source: 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---------------------------------+

The following example shows an array constructor in a **WHERE**
construct statement and in a masked **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

The following example shows a nested **WHERE** construct
statement and masked **ELSEWHERE** statement with a
`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 ...

+-----------------------------End of Fortran 95------------------------------+