Jump to content United States-English
HP.com Home Products and Services Support and Drivers Solutions How to Buy
» Contact HP
More options
HP.com home
HP Fortran 90 Programmer's Reference: HP Series 700/800 Computers > Chapter 5 Expressions and assignment

Expressions

» 

Technical documentation

» Feedback
Content starts here

 » Table of Contents

 » Glossary

 » Index

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

3.14159
! A constant is an expression.
v
! A variable is an expression.
2.0 * a - b ** 3.3
! An expression using *, -, and **.
SIN(a+b) - a * SQRT(b) / d
! An expression using intrinsic functions 
! SQRT and SIN.
a .plus. b - c .times. f
! An expression using user-defined 
! operators -,.plus., and .times..
(/ 1, 2, 3 /) ** 2 + v
! An array expression, using an array 
! constructor.
fcn(x+y) * SUM(aa, DIM=1)
! An expression using the intrinsic 
! function SUM and an external function
! fcn.
.NOT. l
! An expression using the unary logical
! .NOT.intrinsic operator.
(3.0, 5.0) - CONJG(cx)
! 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

Primary

A primary, the simplest form of expression, consists only of an operand, that can be any of:

  • A constant or variable

    1.0, 'ab', a
  • An array element or array section

    a(1,3), a(1,2:3)
  • A character substring or structure component

    ch(1:3), employee%name
  • An array constructor

    (/1.0,2.0/)
  • A structure constructor

    employee(8, "Wilson", 123876)
  • A function reference

    SQRT(x)
  • An expression in parentheses

    (b + SIN(y)**2)

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.

Operators

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

.EQ. .NE.
== /=

Both operands of numeric type (mixed kind parameters allowed), or both of character type, with same kind parameters

Relational

.GT. .GE.
.LT. .LE.
>    >=
<    <=

Both operands of numeric type except complex (mixed kind parameters allowed), or both of character type (same kind parameters)

Logical

.NOT. .AND.
.OR. .EQV.
.NEQV. .XOR.

[1]

Logical (mixed kind parameters)

[1] This is an extension to HP Fortran 90

 

Precedence of operators

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 expression

Within 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.

Constant expression

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:

123                    !an integer literal
"Hello " // " World"   ! a character constant
                       ! expression
3.0_single             ! a real literal constant
                       ! where single is a named
                       ! integer constant
coord(0.0,infinity)    ! a structure constructor
                       ! in which "infinity" is
                       ! a named constant
(/ SQRT(x), x, x*x /)  ! an array constructor in
                       ! which x is a named real
                       ! constant
x*x + 2*x*y + y*y      ! a constant numeric
                       ! expression where x and
                       ! y are named constants
SUM(iterations,DIM=1)  ! reference to a
                       ! transformational
                       ! intrinsic where
                       ! iterations is an 
                       ! array-valued named
                       ! constant
SHAPE(matrix)          ! a reference to an
                       ! inquiry intrinsic in
                       ! which "matrix" is an
                       ! array with constant
                       ! bounds
Initialization expression

An 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:

    • REPEAT

    • RESHAPE

    • SELECTED_INT_KIND

    • SELECTED_REAL_KIND

    • TRANSFER

    • TRIM

  • 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
                       ! expression
pi * r ** 2            ! a constant numeric
                       ! expression where
                       ! pi and r are named 
                       ! constants
ABS(i * j)             ! a reference to an
                       ! elemental intrinsic in
                       ! which i and j are 
                       ! named integer constants
SELECTED_REAL_KIND(7)  ! a reference to a
                       ! transformational
                       ! intrinsic

The following are not valid initialization expressions:

x ** 2.5               ! the power operand is 
                       ! not an integer
LOG(10.0)              ! the intrinsic function
                       ! is neither integer nor
                       ! character type
SUM( (/ i, 2 /) )      ! reference to a 
                       ! prohibited function
Specification expression

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:

    • SELECTED_INT_KIND

    • SELECTED_REAL_KIND

    • TRANSFER

  • 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

    • Size of the array

    • Shape of the array

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

    • May be any type

    • 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

    • Must be scalar valued

    • Must be integer type

    • 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

  • In a CASE 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:

789                    ! an integer literal
                       ! constant
MAX(m+n,0)             ! m and n are integer 
                       ! dummy arguments
LEN(c)                 ! c is a character 
                       ! variable accessible 
                       ! via host association
SELECTED_INT_KIND(5)   ! a reference to a
                       ! transformational 
                       ! intrinsic
UBOUND(arr,DIM=n)      ! a reference to an array
                       ! inquiry intrinsic in 
                       ! which arr is an array
                       ! accessible via USE 
                       ! association and n is a
                       ! variable in common

Interpretation of expressions

Intrinsic operators

  • 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. .

Array operands

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
a =  a+ 1.5
! Increases each element of a by 1.5
c = a * b
! It is equivalent to
! DO i = 1,3
! c(i) = a(i) * b(i)
! ENDDO

Evaluation of expressions

The 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.

HP Extensions

Logical operators and integer operands

The 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.

INTEGER(2) mask2
INTEGER(4) mask4
DATA mask2/ -4 /
DATA mask4/Z"ccc2"/
mask4 = mask4 .NEQV. mask2      !set mask4 to
                                !Z"ffff333e"
mask2 = .NOT. mask4             !set mask2 to
                                !Z"ccc1"
Arithmetic operators and logical operands

Logical 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
INTEGER(1) :: flag1
INTEGER(4) :: flag4
flag4 = boolean4 - boolean1    !set flag4 to
                               !2**16 + 31 
IF (boolean4 > 65536) THEN     !an example of
                               !a relational
                               !operator with
                               !a logical
                               !operand
    flag1 = -(boolean4/65536)  !set flag1 to -1
ENDIF
Integer and logical functions

References 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 intrinsics

In 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:

INTEGER :: mask = 65535
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.
Logical truth values

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. .

Typeless entities

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".

Printable version
Privacy statement Using this site means you accept its terms Feedback to webmaster
© 1996 Hewlett-Packard Development Company, L.P.