Intel® Fortran Compiler Classic and Intel® Fortran Compiler Developer Guide and Reference

ID 767251
Date 3/31/2023
Public

A newer version of this document is available. Customers should click here to go to the newest version.

Document Table of Contents

WHERE

Statement and Construct: Lets you use masked array assignment, which performs an array operation on selected elements. This kind of assignment applies a logical test to an array on an element-by-element basis.

Statement:

WHERE (mask-expr1) assign-stmt

Construct:

[name:]WHERE (mask-expr1)

    [where-body-stmt] ...

[ELSE WHERE(mask-expr2) [name]

    [where-body-stmt] ...]

[ELSE WHERE[name]

    [where-body-stmt] ...]

END WHERE [name]

mask-expr1, mask-expr2

Are logical array expressions (called mask expressions).

assign-stmt

Is an assignment statement of the form: array variable = array expression.

name

Is the name of the WHERE construct.

where-body-stmt

Is one of the following:

  • An assign-stmt

    The assignment can be a defined assignment only if the routine implementing the defined assignment is elemental.

  • A WHERE statement or construct

Description

If a construct name is specified in a WHERE statement, the same name must appear in the corresponding END WHERE statement. The same construct name can optionally appear in any ELSE WHERE statement in the construct. (ELSE WHERE cannot specify a different name.)

In each assignment statement, the mask expression, the variable being assigned to, and the expression on the right side, must all be conformable. Also, the assignment statement cannot be a defined assignment.

Only the WHERE statement (or the first line of the WHERE construct) can be labeled as a branch target statement.

The following shows an example using a WHERE statement:

  INTEGER A, B, C
  DIMENSION A(5), B(5), C(5)
  DATA A /0,1,1,1,0/
  DATA B /10,11,12,13,14/
  C = -1

  WHERE(A .NE. 0) C = B / A

The resulting array C contains: -1,11,12,13, and -1.

The assignment statement is only executed for those elements where the mask is true. Think of the mask expression as being evaluated first into a logical array that has the value true for those elements where A is positive. This array of trues and falses is applied to the arrays A, B and C in the assignment statement. The right side is only evaluated for elements for which the mask is true; assignment on the left side is only performed for those elements for which the mask is true. The elements for which the mask is false do not get assigned a value.

In a WHERE construct, the mask expression is evaluated first and only once. Every assignment statement following the WHERE is executed as if it were a WHERE statement with " mask-expr1" and every assignment statement following the ELSE WHERE is executed as if it were a WHERE statement with ".NOT. mask-expr1". If ELSE WHERE specifies "mask-expr2", it is executed as "(.NOT. mask-expr1) .AND. mask-expr2" during the processing of the ELSE WHERE statement.

You should be careful if the statements have side effects, or modify each other or the mask expression.

The following is an example of the WHERE construct:

  DIMENSION PRESSURE(1000), TEMP(1000), PRECIPITATION(1000)
  WHERE(PRESSURE .GE. 1.0)
    PRESSURE = PRESSURE + 1.0
    TEMP = TEMP - 10.0
  ELSEWHERE
    PRECIPITATION = .TRUE.
  ENDWHERE

The mask is applied to the arguments of functions on the right side of the assignment if they are considered to be elemental functions. Only elemental intrinsics are considered elemental functions. Transformational intrinsics, inquiry intrinsics, and functions or operations defined in the subprogram are considered to be nonelemental functions.

Consider the following example using LOG, an elemental function:

  WHERE(A .GT. 0)  B = LOG(A)

The mask is applied to A, and LOG is executed only for the positive values of A. The result of the LOG is assigned to those elements of B where the mask is true.

Consider the following example using SUM, a nonelemental function:

  REAL A, B
  DIMENSION A(10,10), B(10)
  WHERE(B .GT. 0.0)  B = SUM(A, DIM=1)

Since SUM is nonelemental, it is evaluated fully for all of A. Then, the assignment only happens for those elements for which the mask evaluated to true.

Consider the following example:

  REAL A, B, C
  DIMENSION A(10,10), B(10), C(10)
  WHERE(C .GT. 0.0)  B = SUM(LOG(A), DIM=1)/C

Because SUM is nonelemental, all of its arguments are evaluated fully regardless of whether they are elemental or not. In this example, LOG(A) is fully evaluated for all elements in A even though LOG is elemental. Notice that the mask is applied to the result of the SUM and to C to determine the right side. One way of thinking about this is that everything inside the argument list of a nonelemental function does not use the mask, everything outside does.

Example

  REAL(4) a(20)
  . . .
  WHERE (a > 0.0)
    a = LOG (a)
       !LOG is invoked only for positive elements
  END WHERE

See Also