| Fortran Language Reference Manual, Volume 1 - S-3692-51 | ||
|---|---|---|
| Prev Section | Chapter 7. Expressions and Assignments | Next Section |
An expression is formed from operands, operators, and parentheses. The simplest form of an expression is a constant or a variable.
The values of these simple expressions are the constant value 3.1416, the constant value .TRUE., the value of the variable X, the value of the array Y, the value of the array element Y(K), the value of the array subsection Y(2:10:2), the value of the component N of structure M, and the value of a substring of an array element Y(K), respectively.
An operand in an expression can be one of the following items:
A constant or subobject of a constant
A variable (for example, a scalar, an array, a substring, or a pointer)
An array constructor
A structure constructor
A function reference (returning, for example, a scalar, an array, a character variable, or a pointer)
Another expression in parentheses
The following examples show operands:
A ! scalar or an array B(1) ! array element or function C(3:5) ! array section or a substring (A + COS(X)) ! expression in parentheses (/ 1.2, 2.41 /)! array constructor RATIONAL(1,2) ! structure constructor or function I_PTR ! pointer to an integer target |
There are two forms that operations can take in an expression. One is an operation involving two operands, such as multiplying two numbers together. The other is an operation on one operand, such as making a number negative. These forms are called binary and unary operations, respectively.
Table 7-1 lists the intrinsic operators. You can use function subprograms to define additional operators. User-defined operators are either binary or unary operators.
Table 7-1. Intrinsic Operators and the Allowed Types of their Operands
Operator category | Intrinsic operator | Operand types |
|---|---|---|
Arithmetic | **, *, /, +, -, unary +, unary - | Numeric of any combination of numeric types and kind type parameters or Cray pointer. Cray pointers are only allowed with the + or - operators. |
Character | // | Character of any length. |
Relational | .EQ., .NE., ==, /= | Both of any numeric type and any kind type parameter or Cray pointer, or both of type character with any character length parameter. |
Relational | .GT., .GE., .LT., .LE., >, >=, <, <= | Both of any numeric type (except complex) and any kind type parameter or Cray pointer, or both of type character with any character length parameter. |
Logical | .NOT., .AND., .OR., .XOR., .EQV., .NEQV. | Both of type logical with any combination of kind type parameters. |
Bitwise masking (Boolean) expressions (EXT) | .NOT., .AND., .OR., .XOR., .EQV., .NEQV. | Integer, real, typeless, or Cray pointer. |
Note: The Fortran standard does not specify the bitwise masking (Boolean) expressions, nor does it specify the .XOR. operator as a logical operator.
A binary operator combines two operands, as in the following:
x1 operator x2 |
Examples:
A + B 2 * C |
The examples show an addition between two operands A and B, and a multiplication of two operands, the constant 2 and the operand C.
A unary operation acts on one operand, as in the following:
operator x1 |
Examples:
- C .NOT. L |
The first example results in the value minus C. The second example produces a value that is the logical complement of L; the operator .NOT. is the only intrinsic operator that is a unary operator and is never a binary operator.
Intrinsic operations are those whose definitions are known to the compiler. They are built into Fortran and are always available for use in expressions. Table 7-1, lists the operators built into Fortran as specified by the standard.
The relational operator symbols ==, /=, >, >=, <, and <= are synonyms for the operators .EQ., .NE., .GT., .GE., .LT., and .LE., respectively.
The less than or greater than operation is represented by the <> operator and the .LG. keyword. This operation is suggested by the IEEE standard for floating-point arithmetic, and the Cray Fortran Compiler supports this operator. Only values of type real can appear on either side of the <> or .LG. operators. If the operands are not of the same kind type value, the compiler converts them to equivalent kind types. The <> and .LG. operators perform a less-than-or-greater-than operation as specified in the IEEE standard for floating-point arithmetic.
Note: The Fortran standard does not specify the <> or .LG. operators.
The Cray Fortran Compiler allows abbreviations for the logical and masking operators. The abbreviations .A., .O., .N., and .X. are synonyms for .AND., .OR., .NOT., and .XOR., respectively. If you define the abbreviated operator for any type, the abbreviated form of the intrinsic operator cannot be used in any scope in which the defined operator is accessible.
Note: The Fortran standard does not specify abbreviations for the logical and masking operators.
In addition to the Fortran operators that are intrinsic (built in), there may be user-defined operators in expressions.
Defined operations are those that you define in the Fortran program and are made available to each program unit that uses them. The computation performed by a defined operation is described explicitly in a function that must appear as a subprogram in the Fortran program where it is used. The operator used in a defined operation is called a defined operator. In this way, you extend the repertoire of operations so that computations can be expressed in a natural way using operator notation. Function subprograms that define operators are explained in detail in the Fortran Language Reference Manual, Volume 2.
A defined operator uses a symbol that is either the symbol for an intrinsic operator or is a new operator symbol. The synonyms described above for the relational operators remain synonyms in all contexts, even when there are defined operators. For example, if the operator < is defined for a new type, say STRING, the same definition applies to the operator .LT. for the type STRING; if the operator .LT. is specified as private, the operator < is also private.
A distinction is made between a defined (or new) operator and an extended intrinsic operator. An extended intrinsic operator is one that uses the same symbol as an intrinsically defined Fortran operator, like plus + or multiply *. It also causes the operations to be combined in the same order as is specified for the intrinsic operator. A defined operator is one where the operator symbol is not the same as an intrinsic operator but is new, such as the .INVERSE. operator. Defined operators, however, have a fixed precedence; defined unary operators have the highest precedence of all operators, and defined binary operators have the lowest precedence of all operators. The precedences of all operators are described in more detail in Section 7.2.5.
A defined elemental operation is a defined operation for which the function is elemental.
Note: The masking or Boolean operators and their abbreviations, which are extensions to Fortran, can be redefined as defined operators. If you redefine a masking operator, your definition overrides the intrinsic masking operator definition. See Table 7-1, for a list of the operators.
Expressions are formed by combining operands. Operands can be constants, variables (scalars, array elements, arrays, array sections, structures, structure components, and pointers), array constructors, structure constructors, functions, and parenthesized expressions with intrinsic and defined operators.
The method used to specify the expression formation rules is a collection of syntax rules that determine the forms of expressions. The order of evaluation of the operations in an expression is determined by the usual semantics for the operations, and the syntax rules are designed to be consistent with these semantics. In fact, the order of evaluation defines a precedence order for operators that is summarized in Table 7-2.
Table 7-2. The Hierarchy of Expressions Through Forms
Term | Definition |
|---|---|
expression | [ expression defined_operator ] equivalence_expression |
equivalence_expression | [ equivalence_expression .EQV. ] disjunct_expression equivalence_expression .NEQV. disjunct_expression |
Exclusive OR (extension) | [ disjunct_expression .XOR. ] conjunct_expression |
disjunct_expression | [ disjunct_expression .OR. ] conjunct_expression |
conjunct_expression | [ conjunct_expression .AND. ] not_expression |
not_expression | [ .NOT. ] comparison_expression |
comparison_expression | [ concatenation_expression relational_operator ] concatenation_expression |
concatenation_expression | [ concatenation_expression // ] summation_expression |
summation_expression | [ summation_expression + ] multiplication_expression summation_expression - multiplication_expression + multiplication_expression - multiplication_expression |
multiplication_expression | [ multiplication_expression * ] exponentiation_expression multiplication_expression / exponentiation_expression |
exponentiation_expression | defined_unary_expression [ ** exponentiation_expression ] |
defined_unary_expression | [ defined_operator ] primary |
primary | constant constant_subobject variable array_constructor structure_constructor function_reference (expression) |
The set of syntax rules defines an expression at the highest level in terms of operators and operands, which are themselves expressions. As a result, the formal set of rules is recursive. The basic or lowest level of an expression is a primary, which, for example, can be a variable, a constant, or a function, or recursively an expression enclosed in parentheses. The rules for forming expressions are described from the lowest or most primitive level to the highest or most complex level; that is, the rules are stated from a primary up to an expression.
A primary is defined as follows:
Table 7-3.
| primary | is |
| |
|
| or |
| |
|
| or |
| |
|
| or |
| |
|
| or |
| |
|
| or |
| |
|
| or |
| |
| constant_subobject | is |
|
A variable that is a primary must not be a whole assumed-size array or a section of an assumed-size array name, unless the last subscript position of the array is specified with a scalar subscript or a section subscript in which the upper bound is specified.
The following examples show primaries:
In the previous examples, ONE is a named constant if it has the PARAMETER attribute or appears in a PARAMETER statement. 'ABCS'(I:I) is a constant subobject even though I may be a variable because its parent ('ABCS') is a constant; the reference 'ABCS'(I:I) is a constant subobject because it cannot be defined like a variable can be defined. RATIONAL is a derived type and FCN is a user-defined function.
When an array variable is a primary, the whole array is used, except in a masked assignment statement. In a masked assignment statement, only that part of the array specified by the mask is used.
When a pointer is a primary, the target associated with (pointed to by) the pointer is used, except possibly when the pointer is an actual argument of a procedure, or is an operand of a defined operation or a defined assignment. Whether the pointer or the target is used in these exceptional cases is determined by the procedure invoked by the reference.
Recall that an assumed-size array is a dummy argument whose shape is not completely specified in the subprogram in that the extent in the last dimension is determined by its corresponding actual argument. The implementation model is that the extent in the last dimension is never known to the subprogram but is specified by the use of a subscript, section subscript, or vector subscript expression that defines an upper bound in the last dimension. Unless the extent is specified in this way, such an object must not be used as a primary in an expression. On the other hand, if a subscript, section subscript with an extent for the upper bound, or a vector subscript is specified for the last dimension, the array value has a well-defined shape and hence can be used as a primary in any expression. For example, if A is declared as REAL A(3,*), array A(:,3) has a well-defined shape and can be used as a primary in an expression.
Expressions can be used as actual arguments in procedure references (function references or subroutine calls). Because actual arguments can be expressions involving operations, actual arguments must not contain assumed-size arrays, unless their shape is well-defined, as described above. An actual argument, however, can be just a variable, which then allows the actual argument to be the name of an assumed-size array. This implies that such actual arguments can be assumed-size arrays, unless the procedure requires the shape of the argument to be specified by the actual argument. Most of the intrinsic procedures that allow array arguments require the shape to be specified for the actual array arguments, and therefore assumed-size arrays cannot be used as actual arguments for most intrinsic functions. The exceptions are all references to the intrinsic function LBOUND(3i), and certain references to the intrinsic functions UBOUND(3i) and SIZE(3i).
Defined unary expressions have the highest operator precedence. A defined unary expression is a defined operator followed by a primary. These are defined as follows:
Table 7-4.
| defined_unary_expr | is |
| |
| defined_operator | is |
|
A defined operator must not contain more than 31 letters.
A defined operator must not be the same as any intrinsic operator (.NOT., .AND., .OR., .EQV., .NEQV., .EQ., .NE., .GT., .GE., .LT., .LE., or .LG.) or any logical literal constant (.FALSE. or .TRUE.).
Note: The Fortran standard does not describe the .LG. operator.
A defined operator can be the same as one of the masking or Boolean operators supported by the Cray Fortran Compiler as an extension to the Fortran standard. The corresponding Cray Fortran operator loses its intrinsic properties. Note that the abbreviations .T., .F., .A., .O., .N., and .X. are synonyms for .TRUE., .FALSE., .AND., .OR., .NOT., and .XOR., respectively. If you define the abbreviated operator for any type, the abbreviated form of the intrinsic operator also cannot be used in any scope in which the defined operator is accessible, and the redefined abbreviated logical constants can no longer be used as logical constants.
The following examples show defined unary expressions:
| Expression | Meaning | |
| .INVERSE. B | A defined unary expression (where .INVERSE. is a defined operator) | |
| A | A primary is also a defined unary expression |
An exponentiation expression is an expression in which the operator is the exponentiation operator **. This is defined as follows:
Note that the definition is right recursive (that is, the defined term appears to the right of the operator **) which indicates that the precedence of the ** operator in contexts of equal precedence is right-to-left. Thus, the interpretation of the expression A ** B ** C is A ** ( B ** C ).
The following examples show exponentiation expressions:
A multiplication expression is an expression in which the operator is either * or /. It is defined as follows:
Table 7-6.
| multiplication_expr | is |
| |
|
| or |
|
Note that the definition is left recursive (that is, the defined term appears to the left of the operator * or /) which indicates that the precedence of the * and / operators in contexts of equal precedence is left-to-right. Thus, the interpretation of the expression A * B * C is (A * B) * C, or A / B * C is (A / B) * C. This left-to-right precedence rule applies to the remaining binary operators except the relational operators.
The following examples show multiplication expressions:
A summation expression is an expression in which the operator is either + or -. It is defined as follows:
Table 7-7.
| summation_expr | is |
| |
|
| or |
|
The following examples show summation expressions:
A concatenation expression is an expression in which the operator is //. It is defined as follows:
The following examples show concatenation expressions:
A comparison expression is an expression in which the operator is a relational operator. It is defined as follows:
Table 7-9.
| comparison_expr | is |
| |
| rel_op | is |
| |
|
| or |
| |
|
| or |
| |
|
| or |
| |
|
| or |
| |
|
| or |
| |
EXT |
| or |
| |
|
| or |
| |
|
| or |
| |
|
| or |
| |
|
| or |
| |
|
| or |
| |
|
| or |
| |
EXT |
| or |
|
The operators ==, /=, <, <=, >, >=, and <> are synonyms in all contexts for the operators .EQ., .NE., .LT., .LE., .GT., .GE., and .LG., respectively.
Note: The Fortran standard does not describe the .LG. or <> operators.
Note that the definition of a comparison expression is not recursive, and therefore comparison expressions cannot contain relational operators in contexts of equal precedence.
The following examples show comparison expressions:
A not expression is an expression in which the operator is .NOT.. It is defined as follows:
Note that the definition of a not expression is not recursive, and therefore not expressions cannot contain adjacent .NOT. operators.
The following examples show not expressions:
A conjunct expression is an expression in which the operator is .AND.. It is defined as follows:
Note that the definition of a conjunct expression is left recursive, and therefore the precedence of the .AND. operator in contexts of equal precedence is left-to-right. Thus, the interpretation of the expression A .AND. B .AND. C is (A .AND. B) .AND. C.
The following examples show conjunct expressions:
An inclusive disjunct expression is an expression in which the operator is .OR.. It is defined as follows:
Note that the definition of an inclusive disjunct expression is left recursive, and therefore the precedence of the .OR. operator in contexts of equal precedence is left-to-right. Thus, the interpretation of the expression A .OR. B .OR. C is (A .OR. B) .OR. C.
The following examples show inclusive disjunct expressions:
An equivalence expression is an expression in which the operator is either .EQV. or .NEQV.. It is defined as follows:
Table 7-13.
| equivalence_expr | is |
| |
|
| or |
|
An exclusive disjunct expression is an expression in which the operator is .XOR.. It is defined as follows:
Note: The Fortran standard does not specify the .XOR. operator.
Note the following:
In the following discussion, equivalence expression means either equivalence expression or exclusive disjunct expression.
The definition of an equivalence expression is left recursive, and therefore the precedence of the .EQV. or .NEQV. operators in contexts of equal precedence is left-to-right. Thus, the interpretation of the expression A .EQV. B .NEQV. C is (A .EQV. B) .NEQV. C.
The following examples show equivalence expressions:
The most general form of an expression is defined as follows:
Table 7-15.
| expr | is |
| |
| defined_binary_op | is |
|
Note that the definition of an expression is left recursive, and therefore the precedence of the binary defined operator in contexts of equal precedence is left-to-right. The interpretation of the expression A .PLUS. B .MINUS. C is thus (A .PLUS. B) .MINUS. C (where .MINUS. is a defined operator).
The following examples show expressions:
The previous sections have described in detail the sorts of expressions that can be formed. These expressions form a hierarchy that can best be illustrated by a figure. Figure 7-1, describes the hierarchy by placing the simplest form of an expression, a variable, at the center of a set of nested rectangles. The more general forms of an expression are the enclosing rectangles, from a primary to an exponentiation expression, to a summation expression, and finally to a general expression using a defined binary operator .CROSS.. Figure 7-1 demonstrates that an expression is all of these special case forms, including the simplest form, a primary.
Table 7-2, illustrates the relationship between the different sorts of expressions by summarizing the definitional forms in one table. The simplest form of an expression is at the bottom and is the primary, as in Figure 7-1. The next, more general, form is second from the bottom and is the defined unary expression; it uses the primary in its definition. At the top of the table is the most general form of an expression.
Table 7-16 summarizes the relative precedence of operators, including the precedence when operators of equal precedence are adjacent. An entry of N/A in the rightmost column indicates that the operator cannot appear in such contexts. The left-most column classifies the operators as defined, numeric, character, relational, and logical operators. Note that these operators are not intrinsic operators unless the types of the operands are those specified in Table 7-17.
Table 7-16. Categories of Operations and Relative Precedences
Category of operator | Operator | Precedence | In context of equal precedence |
|---|---|---|---|
Defined | Unary defined-operator | Highest | N/A |
Numeric | ** | . | Right-to-left |
Numeric | * or / | . | Left-to-right |
Numeric | Unary + or - | . | N/A |
Numeric | Binary + or - | . | Left-to-right |
Character | // | . | Left-to-right |
Relational | .EQ., .NE., .LT., .LE., .GT., .GE., .LG., ==, /=, <, <=, >, >=, <> | . | N/A |
Logical or Boolean | .NOT. | . | N/A |
Logical or Boolean | .AND. | . | Left-to-right |
Logical or Boolean | .OR. | . | Left-to-right |
Logical | .EQV. or .NEQV. | . | Left-to-right |
Logical or Boolean | .XOR. | . | Left-to-right |
Defined | Binary defined-operator | Lowest | Left-to-right |
For example, consider the following expression:
A .AND. B .AND. C .OR. D |
Table 7-2, indicates that the .AND. operator is of higher precedence than the .OR. operator, and the .AND. operators are combined left-to-right when in contexts of equal precedence; thus, A and B are combined by the .AND. operator, the result A .AND. B is combined with C using the .AND. operator, and that result is combined with D using the .OR. operator. Thus, this expression is interpreted the same way as the following fully parenthesized expression:
(((A .AND. B) .AND. C) .OR. D) |
Notice that the defined operators have fixed precedences; defined unary operators have the highest precedence of all operators and are all of equal precedence; defined binary operators have the lowest precedence, are all of equal precedence, and are combined left-to-right when in contexts of equal precedence. Both kinds of defined operators may have multiple definitions in the program unit and therefore may be generic just as intrinsic operators and intrinsic procedures are generic.
As a consequence of the expression formation rules, unary operators cannot appear in a context of equal precedence; the precedence must be specified by parentheses. There is thus no left-to-right or right-to-left rule for any unary operators. Similarly, the relational operators cannot appear in a context of equal precedence; consequently, there is no left-to-right or right-to-left rule for the relational operators. Use of some of the operators as Boolean or masking operators is an extension to the Fortran standard that is supported by the Cray Fortran Compiler.
Note: The Fortran standard does not specify the use of operators as Boolean or masking operators.
Intrinsic operations are those known to the processor. For an operation to be intrinsic, an intrinsic operator symbol must be used, and the operands must be of the intrinsic types specified in Table 7-17.
Note: In the following table, the symbols I, R, Z, C, L, B, and P stand for the types integer, real, complex, character, logical, Boolean, and Cray pointer, respectively. Where more than one type for x2 is given, the type of the result of the operation is given in the same relative position in the next column. Boolean and Cray pointer types are extensions of the Fortran standard.
Table 7-17. Operand Types and Results for Intrinsic Operations
Intrinsic operator | Type of x1 | Type of x2 | Type of result |
|---|---|---|---|
Unary +, - |
| I, R, Z, B, P | I, R, Z, I, P |
Binary +, -, *, /, ** | I | I, R, Z, B, P | I, R, Z, I, P |
| R | I, R, Z, B | R, R, Z, R |
| Z | I, R, Z | Z, Z, Z |
| B | I, R, B, P | I, R, B, P |
| P | I, B, P | P, P, P |
| (For Cray pointer, only + and - are allowed.) |
|
|
// | C | C | C |
.EQ., ==, .NE., /= | I | I, R, Z, B, P | L, L, L, L, L |
| R | I, R, Z, B, P | L, L, L, L, L |
| Z | I, R, Z, B, P | L, L, L, L, L |
| B | I, R, Z, B, P | L, L, L, L, L |
| P | I, R, Z, B, P | L, L, L, L, L |
| C | C | L |
.GT., >, .GE., >=, .LT., <, .LE., <= | I | I, R, B, P | L, L, L, L |
| R | I, R, B | L, L, L |
| C | C | L |
| P | I, P | L, L |
.LG., <> | R | R | L |
.NOT. |
| L | L |
|
| I, R, B | B |
.AND., .OR., .EQV., .NEQV., .XOR. | L | L | L |
| I, R, B | I, R, B | B |
Note: The Fortran standard does not specify the use of type Boolean or the use of type Boolean in masking expressions, nor does it describe the .LG. and <> operators.
The intrinsic operations are either binary or unary. The binary operations use the binary intrinsic operator symbols +, -, *, /, **, //, .EQ., .NE., .LT., .GT., .LE., .GE., and .LG.(and their synonyms ==, /=, <>, <, >=, and <>), .AND., .OR., .XOR., .EQV., and .NEQV.. The unary operations use the unary intrinsic operator symbols +, -, and .NOT..
Note that the intrinsic operators .AND., .OR., .NOT., and .XOR. can be abbreviated as .A., .O., .N., or .X.. If a user-defined operator with the same name as the abbreviated name is accessible in a scope, the abbreviated forms of these operators may not be used as synonyms for .AND., .OR., .NOT., or .XOR..
The intrinsic operations are divided into five classes with different rules and restrictions for the types of the operands. The five classes are numeric intrinsic, character intrinsic, logical intrinsic, relational intrinsic operations, and bitwise masking expressions.
The numeric intrinsic operations use the intrinsic operators +, -, *, /, and **. The operands can be of any numeric type and with any kind type parameters. The result of the operation is of a type specified by Table 7-17, and has type parameters as specified in Section 7.2.8.2.
For example, the following expressions, in which I, R, D, and Z are declared to be of types integer, real, double-precision real, and complex, have the types and type parameters of the variables R, I, D, and Z, respectively:
I + R I * I I - D I / Z |
There is only one character intrinsic operation; it uses the intrinsic operator //. The result of a character intrinsic operation is type character.
The logical intrinsic operations use the intrinsic operators .AND., .OR., .NOT., .EQV., and .NEQV., respectively. The result of a logical intrinsic operation is type logical and has type parameters as specified in Section 7.2.8.2.
The relational intrinsic operations use the intrinsic operators .EQ., .NE., .GT., .GE., .LT., .LE., or .LG. or their symbolic synonyms. A relational intrinsic operation is a numeric relational intrinsic operation if its operands are of type integer, real, or complex. A relational intrinsic operation is a character relational intrinsic operation if its operands are of type character. The result of either kind of relational operation is type logical and has type parameters as specified in Section 7.2.8.2.
Note: The Fortran standard does not describe the .LG. operator.
The operators .NOT., .AND., .OR., .EQV., and .XOR. can also be used in the Cray Fortran Compiler's bitwise masking expressions; these are extensions to the Fortran standard. The result is Boolean (or typeless) and has no kind type parameters.
A defined operation is any nonintrinsic operation that is interpreted and evaluated by a function subprogram specified by an interface block with a generic specifier of the following form:
OPERATOR (defined_operator) |
A defined elemental operation is a defined operation for which the function is elemental.
A defined operation uses either a defined operator or an intrinsic operator symbol, and it is either unary or binary. Its forms are as follows:
|
The terms intrinsic_unary_op and intrinsic_binary_op include all intrinsically defined operators; these terms are not specifically defined in any syntax rules.
x1 and x2 are operands. When an intrinsic operator symbol is used, the type of x2 (for a unary operator) and types of x1 and x2 (for a binary operator) must not be the same as the types of the operands specified in Table 7-17, for the particular intrinsic operator symbol. Thus, you cannot redefine intrinsic operations on intrinsic types.
When a defined operation uses an intrinsic operator symbol, the generic properties of that operator are extended to the new types specified by the interface block. When a defined operation uses a defined operator, the defined operation is called an extension operation, and the operator is called an extension operator. An extension operator can have generic properties by specifying more than one function subprogram in an interface block with a generic specifier of the form OPERATOR (defined_operator).
The data type, type parameters, and shape of a complete expression are determined by the data type, type parameters, and shape of each constant, variable, constructor, and function reference appearing in the expression. The determination is inside-out in the sense that the properties are determined first for the primaries. These properties are then determined repeatedly for the operations in precedence order, resulting eventually in the properties for the expression.
For example, consider the expression A + B * C, where A, B, and C are of numeric type. First, the data types, type parameter values, and shapes of the three variables A, B, and C are determined. Because * has a higher precedence than +, the operation B * C is performed first. The type, type parameters, and shape of the expression B * C are determined next, and then these properties for the entire expression are determined from those of A and B * C.
A defined elemental operation is a defined operation for which the function is elemental.
The type, type parameters, and shape of a primary that is a nonpointer variable or constant are straightforward because these properties are determined by specification statements for the variable or named constant, or by the form of the constant. For example, if A is a variable, its declaration in a specification statement such as the following determines it as an explicit-shaped array of type real with a default kind parameter:
REAL A(10, 10) |
For a constant such as the following, the form of the constant indicates that it is a scalar constant of type complex and of default kind:
(1.3, 2.9) |
For a pointer variable, the type, type parameters, and rank are determined by the declaration of the pointer variable. However, if the pointer is of deferred shape, the shape (in particular, the extents in each dimension) is determined by the target of the pointer. Consider the following declarations and assume that pointer A is associated with the target B:
REAL, POINTER :: A(:, :) REAL, TARGET :: B(10, 20) |
The shape of A is (10, 20).
The type and type parameters of an array constructor are determined by the contents of the constructor. Unless the element is of type Boolean (or typeless), its type and type parameters are those of any element of the constructor because they must all be of the same type and type parameters. If the element is of type Boolean, the type and kind type of the array constructor are the same as the default integer type. Therefore, the type and type parameters of the following array constructor are integer and kind value 1:
(/ 1_1, 123_1, -10_1 /) |
Its shape is always of rank one and of size equal to the number of elements.
The type of a structure constructor is the derived type or type alias used as the name of the constructor. A structure has no type parameters. So, the type of the following structure constructor is the derived type PERSON:
PERSON(56, 'Father') |
(See Section 4.8, for the type definition PERSON.)
A structure constructor is always a scalar.
The type, type parameters, and shape of a function are determined by one of the following:
An implicit type declaration for the function within the program unit referencing the function
An explicit type declaration for the function within the program unit referencing the function (just like a variable)
An explicit interface to the function. (When the interface is not explicit, the function is either an external function or a statement function.)
If the interface is explicit, the type, type parameter, and shape are determined by one of the following:
The type and other specification statements for the function in an interface block within the program unit referencing the function
The type and other specification statements for the internal or module procedure specifying the function
The description of the particular intrinsic function being referenced
Note, however, that because intrinsic functions and functions with interface blocks can be generic, these properties are determined by the type, type parameters, and shapes of the actual arguments of the particular function reference.
For example, consider the following statements as part of the program unit specifying an internal function FCN:
REAL FUNCTION FCN(X) DIMENSION FCN(10, 15) |
A reference to FCN(3.3) is of type default real with shape (10,15). As a second example, consider the following: