 |
» |
|
|
 |
An expression can consist of operands, operators, and parentheses,
and defines a computation that upon evaluation yields a result.
This result can be an operand in a larger expression. Expressions
are used in many contexts in Fortran 90, for example, in
assignment statements, in procedure references, and in output statements.
An expression has a value and therefore a type and a kind. Expressions
are formed from operands and operators that may be intrinsic or
user-defined. An operand may be a constant, variable, array element, array
section, structure component, substring, array constructor, structure
constructor, function reference, or an expression enclosed in parentheses.
Parentheses have the usual mathematical meaning. An
operator can be an intrinsic operator or a
user-defined operator. The intrinsic operators
are defined within the language; each has a specific meaning for
a set of defined operand types. The range of types that an intrinsic
operator accepts can be extended, and entirely new operators can
be defined, by inclusion of an appropriate interface block and function
subprogram definitions. Details are given in Chapter 7. Examples ! A constant is an expression. |
! A variable is an expression. |
! An expression using *, -, and **. |
SIN(a+b) - a * SQRT(b) / d |
! An expression using intrinsic functions |
! An expression using user-defined |
! operators -,.plus., and .times.. |
! An array expression, using an array |
fcn(x+y) * SUM(aa, DIM=1) |
! An expression using the intrinsic |
! function SUM and an external function |
! An expression using the unary logical |
! .NOT.intrinsic operator. |
! An expression using a complex constant |
! and intrinsic function CONJG. |
rational( 1, 2*j) * rational( i, j ) |
! An expression using the structure |
! constructor rational and an extended |
! definition of the intrinsic operator *. |
 |
Formation of expressions |  |
A
primary, the simplest form of expression, consists
only of an operand, that can be any of: An array element or array section A character substring or structure component A structure constructor employee(8, "Wilson", 123876) |
An expression in parentheses
When
the primary is an array variable, the complete array is referenced.
An assumed-size array variable cannot be a primary. An array section
of an assumed-size array can be a primary if the extent of the last
dimension of the section is defined by the use of a subscript, a
section subscript with an extent for the upper bound, or a vector
subscript. (See Chapter 4 for a discussion of arrays.) If the primary has the POINTER
attribute, then the target associated with it is used as the operand. The more general form of an expression is: [operand1] operator operand2 |
If operand1 is present then the
operator is binary (operates on two operands), otherwise it is a
unary operator (operates on only one operand). Table 5-1 “ Intrinsic operators” lists the intrinsic
operators and the types of operands for which they have a defined
meaning. Note that: The operators +,
-, /,
*, and **
are used for addition, subtraction, division, multiplication, and
exponentiation respectively. The
operators + and
- can be used
as unary or binary operators. The operator //
is used to concatenate two strings.
The
Standard does not allow two adjacent operators. For example, i + -j
is not valid; this example should be rewritten as i + (-j).
However, HP Fortran 90 does allow the exponentiation
operator to be followed by a signed entity, for example, i ** -j is
permitted and is equivalent to i ** (-j). The
relational operators .EQ.,
.NE., and others
are used to compare values. Logical operators are available to perform Boolean
arithmetic; these are .NOT.,
.AND., .OR.,
.EQV., and .NEQV. .
Their behavior is described in Table 5-4 “ Logical operators”.
As an extension, HP Fortran
90 also supports the .XOR.
operator, which is equivalent to .NEQV..
A more detailed description of the interpretation of the operators
is given in Table 5-1 “ Intrinsic operators”. Table 5-1 Intrinsic operators Category | Operators | Valid
operand types | Arithmetic | | Numeric,
of any combination of types and kind parameters | Character | // | Character,
of any length but same kind parameters | Relational | | Both
operands of numeric type (mixed kind parameters allowed), or both
of character type, with same kind parameters | Relational | | Both
operands of numeric type except complex (mixed kind parameters allowed),
or both of character type (same kind parameters) | Logical | [1] | Logical
(mixed kind parameters) |
When an expression expands to: operand1 operator1 operand2 operator2 operand3
... it
is necessary to define the order in which the operators will be
applied. Each operator is assigned a precedence. The defined order
of evaluation is that any subexpressions containing an operator
with higher precedence than the adjacent operators will be evaluated
first. Where operators are of equal precedence, evaluation will
be from left to right, except for the exponentiation operator (**),
which is evaluated from right to left. Any expression or subexpression
may be enclosed in parentheses; such expressions are always evaluated
first using the rules explained above. This usage of parentheses
is therefore equivalent to normal mathematical usage. Table 5-2 “ Operator precedence” lists the precedence of
the operators; it is followed by some examples. Table 5-2 Operator precedence Precedence | Operators | Highest | User
defined unary operators | | ** | | * / | | Unary
+ Unary - | | + - | | // | | .EQ. .NE. .LT. .LE. .GT. .GE. |
| | .NOT. | | .AND. | | .OR. | | .EQV. .NEQV. .XOR. | Lowest | User defined
binary operators |
Table 5-3 “Operator precedence: examples” provides examples
to illustrate operator precedence. Table 5-3 Operator precedence: examples Expression | How evaluated | Explanation |
|---|
a+b*c | a + (b*c) | *
has a higher precedence than +. | a/b*c | (a/b)*c | /
and * have the
same precedence, and evaluation is left to right. | a**b**c | a**(b**c) | **
evaluates right to left. | a.AND.b.AND.c.OR.d | ((a.AND.b).AND.c).OR.d) | Logical
operators evaluate left to right. |
Special forms of expressionWithin
certain language constructs only restricted forms of expression
are permitted. For example, the value of an entity with the PARAMETER
attribute—that is, a named constant—may be defined
by an expression, but it must be possible to evaluate the expression
during compilation—the expression must be an initialization
expression, a restricted form of constant expression. The bound of an array that is a dummy array argument in a
subprogram may be an expression, but it must be possible to evaluate
this expression on entry to the subprogram the expression must be
a specification expression. Constant expressions, initialization expressions, and specification
expressions are defined in the following sections. A
constant expression is either a constant or
an expression containing only intrinsic operators and constant operands.
In this context, a constant includes any well-defined part of a
constant—for example, a substring with constant start and
end points, or an array or structure constructor where all the expressions
used are constants or constant expressions. A constant expression
can also include references to intrinsic functions that can be fully
evaluated at compilation time. Certain intrinsics cannot be evaluated by the compiler; these
are ALLOCATED,
ASSOCIATED, and
PRESENT, and
any inquiry intrinsic with arguments such that the property inquired
about (for example type parameters or array bounds) is not constant. A constant expression may appear in any context in which a
general expression may be used. Examples of a constant expression are: "Hello " // " World" ! a character constant |
3.0_single ! a real literal constant |
! where single is a named |
coord(0.0,infinity) ! a structure constructor |
(/ SQRT(x), x, x*x /) ! an array constructor in |
! which x is a named real |
x*x + 2*x*y + y*y ! a constant numeric |
SUM(iterations,DIM=1) ! reference to a |
SHAPE(matrix) ! a reference to an |
Initialization expressionAn
initialization expression
is a constant expression with the following further restrictions: Exponentiation is only allowed if
the second operand is an integer. Any subexpression used within the expression must
be an initialization expression. All arguments to intrinsic function references must
be initialization expressions. Only the following transformational intrinsic functions
may be referenced: Any inquiry intrinsic that is referenced may only
interrogate a property of an entity ( such as bounds or kind type
parameter) if the property is a constant. Any elemental intrinsic functions used must have
integer or character arguments and an integer or character result.
Initialization expressions are required in the following situations: When defining values of named constants. When specifying a kind parameter in a type specification
statement. When specifying the KIND
dummy argument of a type conversion intrinsic function. For initial values in type declaration statements. For expressions in structure constructors in DATA
statements. For
case values in CASE
statements. For subscript expressions or substring ranges in
EQUIVALENCE statements.
The following are valid initialization expressions: -456 ! an integer literal |
("Hello "// "World") ! a character constant |
pi * r ** 2 ! a constant numeric |
ABS(i * j) ! a reference to an |
! named integer constants |
SELECTED_REAL_KIND(7) ! a reference to a |
The following are not valid initialization expressions: x ** 2.5 ! the power operand is |
LOG(10.0) ! the intrinsic function |
SUM( (/ i, 2 /) ) ! reference to a |
A
specification expression is an expression that
has a scalar value, is of type integer, and can be evaluated on
entry to the scoping unit in which it appears. This imposes the
following conditions on primaries used in a specification expression: Constants or variables must be available
by argument, host, or use association or be in common. Any variable referenced must not be a dummy argument
with either the OPTIONAL
attribute or the INTENT(OUT)
attribute. All arguments to intrinsic function references must
be specification expressions. Elemental intrinsic function references must return
integer results. Only the following transformational intrinsic functions
may be referenced: The inquiry intrinsics ALLOCATED,
ASSOCIATED, and
PRESENT may not
be referenced. Other
inquiry intrinsics may be referenced provided that the property
interrogated is not defined by either a pointer assignment or ALLOCATE statement;
furthermore, an inquiry intrinsic may not interrogate the following
properties of an assumed size array: Upper bound of the last
dimension Extent of the last dimension
Note that there are some important differences between specification
expressions and initialization expressions; the differences are
summarized below: Initialization expressions May be either scalar
or array valued Must be a constant expression May reference an inquiry intrinsic (except for ALLOCATED,
ASSOCIATED, and
PRESENT) to interrogate
a property of an entity provided that the property is constant
Specification expressions May reference variables via host, argument, or use
association May reference variables in common Subject to certain restrictions, may reference an
inquiry intrinsic (except for ALLOCATED,
ASSOCIATED, and
PRESENT) to interrogate
a property of an entity; the property need not be constant.
Specification expressions may be used where any arbitrary
expression is allowed, and they may also be used to declare the
bounds of an array and the length of a character variable. They
may not be used: As subscripts or substring ranges
in an EQUIVALENCE
statement As a KIND
parameter in a type declaration statement As initial values in a PARAMETER
or type declaration statement As
the limits or increment of an implied DO
loop in a DATA
statement As a KIND
dummy argument to type conversion intrinsics
Examples of specification expressions are: MAX(m+n,0) ! m and n are integer |
LEN(c) ! c is a character |
SELECTED_INT_KIND(5) ! a reference to a |
UBOUND(arr,DIM=n) ! a reference to an array |
Interpretation of expressions |  |
Arithmetic
operators (+, -, /, *, **) The
two operands may be of different numeric types or different kind
type parameters. The type of the result is: The type of either operand
if the types and kind type parameters are the same. The type of the operand with the larger kind type
parameter if the types are the same but not the kind type parameters. Complex if either operand is complex and the other
is not. Real if either operand is real and the other is
not complex.
Except for a value raised to an integer power, each operand
that differs in type or kind type parameter from that of the result
is converted to a value with the type and kind type of the result
before the operation is performed. The arithmetic operators behave as expected, with the following
qualifications: The division of an integer
by an integer is defined to be the integer closest to the true result
that is between zero and the true result. Exponentiation of an integer to a negative integer, i1**i2, where
i2 is negative,
is interpreted as 1/(i1**(-i2)),
where the division is interpreted as described for division of one
integer by another. If x1 and x2
are real with x1 negative, then x1**x2
could be an invalid expression, as the result could be complex.
Note, however, that CMPLX(x1)**x2
is valid; the result is the principal value.
Relational operators (.EQ.,
.NE., .GT.,
.GE., .LT.,
.LE., ==,
/=, >,
>=, <,
<=) If the operands of a relational operator are numerical expressions
with different type or kind type parameters, the operands are converted
to the type and kind type parameters that the sum of the operands
would have, and then they are compared. If the operands are character
expressions, the shorter operand is blank padded to the length of
the other prior to the comparison. The comparison starts at the
first character and proceeds until a character differs or equality
is confirmed. The collating sequence is defined in Appendix C. Character operators (//) In a
character
concatenation
operation, each operand must be type character and have the same
kind type parameter. The character length parameter of the result
is the sum of the character length parameters of the operands. Logical operators (.AND.,
.OR., .EQV.,
.NEQV., .XOR.,
.NOT.) In a standard conforming program the two operands must be
of logical type but may be of different kind type parameters. The
type of the result is: The type of either operand
if the kind type parameters are the same. The type of the operand with the larger kind type
parameter if the kind type parameters are not the same.
An operand that differs in kind type from that of the result
is converted to a value with the type and kind type of the result
before the operation is performed.
As an extension, HP Fortran 90 permits the
operands to be of type integer (see “HP Extensions”). The behavior of the logical operators is as shown in Table 5-4 “ Logical operators”. Table 5-4 Logical operators opnd1 | opnd2 | .AND. | .OR. | .EQV. | .NEQV.
and .XOR. | .NOT.
opnd1 |
|---|
.TRUE. | .TRUE. | .TRUE. | .TRUE. | .TRUE. | .FALSE. | .FALSE. | .TRUE. | .FALSE. | .FALSE. | .TRUE. | .FALSE. | .TRUE. | .FALSE. | .FALSE. | .TRUE. | .FALSE. | .TRUE. | .FALSE. | .TRUE. | .TRUE. | .FALSE. | .FALSE. | .FALSE. | .FALSE. | .TRUE. | .FALSE. | .TRUE. |
HP Fortran 90 accepts .XOR.
as an alternative notation for .NEQV.
. If
both operands are arrays, then they must have the same shape. If
one operand is a scalar, then it is treated as if it were an array
of the same shape as the other operand, in which all elements have
the value of the scalar. The result of the operation is an array
in which each element is the result of applying the operator repeatedly
to corresponding elements of the two operands. Example real,dimension(3):: a, b, c |
! Increases each element of a by 1.5 |
Evaluation of expressionsThe
definition of the language allows the compiler to generate code
that evaluates an expression by any sequence that produces a result
mathematically equivalent to the sequence implied by the Fortran 90
statement. This permits optimization of the code, including, for
example, the reordering of expressions and the promotion of common
subexpressions. Because the order of evaluation of an expression is not defined
it is invalid for any function reference within an expression to
modify any of the other components appearing within the expression.
Thus, for example, fun(x)+x is
indeterminate if the reference to fun
modifies the value of the argument x. Logical operators and integer operandsThe
logical operators can be used with integer operands to perform bit
operations. The logical operations are performed for each bit of
the binary representations of the integers. When the operands are
of different lengths, the shorter is considered to be extended to
the length of the other operand as if it were a signed integer,
and the result has the length of the longer operand. The following example shows the use of logical operators to
perform bit-masking operations. mask4 = mask4 .NEQV. mask2 !set mask4 to |
mask2 = .NOT. mask4 !set mask2 to |
Arithmetic operators and logical operandsLogical
and integer types can be combined with the arithmetic operators.
The logical variable is treated as an integer of equivalent size,
and the result of the operation is an integer value. When different
lengths of operands are involved, the shorter is considered extended
as a signed integer. The following example shows how logical operands may be used
interchangeably with integer operands LOGICAL(1) :: boolean1 = -4 |
LOGICAL(4) :: boolean4 = 2**16 + 27 |
flag4 = boolean4 - boolean1 !set flag4 to |
IF (boolean4 > 65536) THEN !an example of |
flag1 = -(boolean4/65536) !set flag1 to -1 |
Integer and logical functionsReferences
to functions are classified as expressions, and HP Fortran 90
allows integer function results to be used in logical expressions,
and also user-defined logical function results to be used in integer
expressions. Bit manipulation intrinsicsIn general, an integer actual argument
may not be used in a reference to a procedure when the corresponding
dummy argument is of type logical, nor may a logical actual argument
be used when the dummy argument is of type integer. The only relaxation
of this rule allowed by HP Fortran 90 is in calls
to bit manipulation intrinsics, when logical and integer arguments
may be used interchangeably. See Chapter 11 for a list of the bit manipulation
intrinsics. The following code contains a standard-conforming reference
to a bit manipulation intrinsic: LOGICAL :: is_even = .FALSE. |
IF (IAND(mask,1) /= 0) is_even = .TRUE. |
The following code contains a similar but nonstandard reference
supported by HP Fortran 90: LOGICAL :: mask = z"ffff" |
INTEGER :: is_even = .FALSE. |
IF (IAND(mask,1)) is_even = .TRUE. |
In a standard-conforming program, a logical variable or expression
will be .TRUE.
(the value 1
in HP Fortran 90) or .FALSE.
(the value 0
in HP Fortran 90). In nonstandard conforming programs
involving logical operators with integer operands or arithmetic
operators with logical operands, a logical variable or expression
may have a value other than 1
or 0. In this
case, any nonzero value is considered to be .TRUE.
and a zero value .FALSE.
. The
Fortran 90 Standard defines a specific set of integer literals
known collectively as BOZ constants that represent values in binary,
octal, or hexadecimal. These constants may be used in DATA
statements as initial values. In HP Fortran 90,
BOZ constants assume a type and kind that is compatible with the
context in which they appear, and may be used interchangeably wherever
integer, logical, real, or complex literals are allowed. HP Fortran 90
allows Hollerith constants to be used in the same contexts as BOZ
constants and also wherever a character literal may appear. BOZ
constants and Hollerith constants are collectively known as typeless
constants and are described in Chapter 3 in the section
"Representation of Literal Constants"; the rules
associated with the use of these constants are also described in
Chapter 3, in the section "Typeless Constants".
|