[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

HP Fortran for OpenVMS
Language Reference Manual


Previous Contents Index


Chapter 4
Expressions and Assignment Statements

This chapter describes:

4.1 Expressions

An expression represents either a data reference or a computation, and is formed from operators, operands, and parentheses. The result of an expression is either a scalar value or an array of scalar values.

If the value of an expression is of intrinsic type, it has a kind type parameter. (If the value is of intrinsic type CHARACTER, it also has a length parameter.) If the value of an expression is of derived type, it has no kind type parameter.

An operand is a scalar or array. An operator can be either intrinsic or defined. An intrinsic operator is known to the compiler and is always available to any program unit. A defined operator is described explicitly by a user in a function subprogram and is available to each program unit that uses the subprogram.

The simplest form of an expression (a primary) can be any of the following:

  • A constant; for example, 4.2
  • A subobject of a constant; for example, ' LMNOP ' (2:4)
  • A variable; for example, VAR_1
  • A structure constructor; for example, EMPLOYEE(3472, "JOHN DOE")
  • An array constructor; for example, (/12.0,16.0/)
  • A function reference; for example, COS(X)
  • Another expression in parentheses; for example, (I+5)

Any variable or function reference used as an operand in an expression must be defined at the time the reference is executed. If the operand is a pointer, it must be associated with a target object that is defined. An integer operand must be defined with an integer value rather than a statement label value. All of the characters in a character data object reference must be defined.

When a reference to an array or an array section is made, all of the selected elements must be defined. When a structure is referenced, all of the components must be defined.

In an expression that has intrinsic operators with an array as an operand, the operation is performed on each element of the array. In expressions with more than one array operand, the arrays must be conformable (they must have the same shape). The operation is applied to corresponding elements of the arrays, and the result is an array of the same shape (the same rank and extents) as the operands.

In an expression that has intrinsic operators with a pointer as an operand, the operation is performed on the value of the target associated with the pointer.

For defined operators, operations on arrays and pointers are determined by the procedure defining the operation.

A scalar is conformable with any array. If one operand of an expression is an array and another operand is a scalar, it is as if the value of the scalar were replicated to form an array of the same shape as the array operand. The result is an array of the same shape as the array operand.

The following sections describe numeric, character, relational, and logical expressions; defined operations; a summary of operator precedence; and initialization and specification expressions.

For More Information:

4.1.1 Numeric Expressions

Numeric expressions express numeric computations, and are formed with numeric operands and numeric operators. The evaluation of a numeric operation yields a single numeric value.

The term numeric includes logical data, because logical data is treated as integer data when used in a numeric context. The default for .TRUE. is --1; .FALSE. is 0.

Numeric operators specify computations to be performed on the values of numeric operands. The result is a scalar numeric value or an array whose elements are scalar numeric values. The following are numeric operators:

Operator Function
** Exponentiation
* Multiplication
/ Division
+ Addition or unary plus (identity)
-- Subtraction or unary minus (negation)

Unary operators operate on a single operand. Binary operators operate on a pair of operands. The plus and minus operators can be unary or binary. When they are unary operators, the plus or minus operators precede a single operand and denote a positive (identity) or negative (negation) value, respectively. The exponentiation, multiplication, and division operators are binary operators.

Valid numeric operations must have results that are defined by the arithmetic used by the processor. For example, raising a negative-valued real to a real power is invalid.

Numeric expressions are evaluated in an order determined by a precedence associated with each operator, as follows (see also Section 4.1.6):

Operator Precedence
** Highest
* and / .
Unary + and -- .
Binary + and -- Lowest

Operators with equal precedence are evaluated in left-to-right order. However, exponentiation is evaluated from right to left. For example, A**B**C is evaluated as A**(B**C). B**C is evaluated first, then A is raised to the resulting power.

Normally, two operators cannot appear together. However, HP Fortran allows two consecutive operators if the second operator is a plus or minus.

Examples

In the following example, the exponentiation operator is evaluated first because it takes precedence over the multiplication operator:

A**B*C is evaluated as (A**B)*C

Ordinarily, the exponentiation operator would be evaluated first in the following example. However, because HP Fortran allows the combination of the exponentiation and minus operators, the exponentiation operator is not evaluated until the minus operator is evaluated:

A**-B*C is evaluated as A**(-(B*C))

Note that the multiplication operator is evaluated first, since it takes precedence over the minus operator.

When consecutive operators are used with constants, the unary plus or minus before the constant is treated the same as any other operator. This can produce unexpected results. In the following example, the multiplication operator is evaluated first, since it takes precedence over the minus operator:

X/-15.0*Y is evaluated as X/-(15.0*Y)

4.1.1.1 Using Parentheses in Numeric Expressions

You can use parentheses to force a particular order of evaluation. When part of an expression is enclosed in parentheses, that part is evaluated first. The resulting value is used in the evaluation of the remainder of the expression.

In the following examples, the numbers below the operators indicate a possible order of evaluation. Alternative evaluation orders are possible in the first three examples because they contain operators of equal precedence that are not enclosed in parentheses. In these cases, the compiler is free to evaluate operators of equal precedence in any order, as long as the result is the same as the result gained by the algebraic left-to-right order of evaluation.

4 + 3 * 2 - 6 / 2 = 7
<uparrow symbol> <uparrow symbol> <uparrow symbol> <uparrow symbol>
2 1 4 3

(4 + 3) * 2 - 6 / 2 = 11
<uparrow symbol> <uparrow symbol> <uparrow symbol> <uparrow symbol>
1 2 4 3

(4 + 3 * 2 - 6) / 2 = 2
<uparrow symbol> <uparrow symbol> <uparrow symbol> <uparrow symbol>
2 1 3 4

((4+3) * 2 - 6) / 2 = 4
<uparrow symbol> <uparrow symbol> <uparrow symbol> <uparrow symbol>
1 2 3 4

Expressions within parentheses are evaluated according to the normal order of precedence. In expressions containing nested parentheses, the innermost parentheses are evaluated first.

Nonessential parentheses do not affect expression evaluation, as shown in the following example:

4 + (3*2) - (6/2)

However, using parentheses to specify the evaluation order is often important in high-accuracy numerical computations. In such computations, evaluation orders that are algebraically equivalent may not be computationally equivalent when processed by a computer (because of the way intermediate results are rounded off).

Parentheses can be used in argument lists to force a given argument to be treated as an expression, rather than as the address of a memory item.

4.1.1.2 Data Type of Numeric Expressions

If every operand in a numeric expression is of the same data type, the result is also of that type.

If operands of different data types are combined in an expression, the evaluation of that expression and the data type of the resulting value depend on the ranking associated with each data type. The following table shows the ranking assigned to each data type:

Data Type Ranking
LOGICAL(1) and BYTE Lowest
LOGICAL(2) .
LOGICAL(4) .
LOGICAL(8) .
INTEGER(1) .
INTEGER(2) .
INTEGER(4) .
INTEGER(8) .
REAL(4) .
REAL(8) 1 .
REAL(16) .
COMPLEX(4) .
COMPLEX(8) 2 .
COMPLEX(16) Highest

1DOUBLE PRECISION
2DOUBLE COMPLEX

The data type of the value produced by an operation on two numeric operands of different data types is the data type of the highest-ranking operand in the operation. For example, the value resulting from an operation on an integer and a real operand is of real type. However, an operation involving a COMPLEX(4) or COMPLEX(8) data type and a DOUBLE PRECISION data type produces a COMPLEX(8) result.

The data type of an expression is the data type of the result of the last operation in that expression, and is determined according to the following conventions:

  • Integer operations: Integer operations are performed only on integer operands. Note that logical entities used in a numeric context are treated as integers. In integer arithmetic, any fraction resulting from division is truncated, not rounded. For example, the result of 1/4 + 1/4 + 1/4 + 1/4 is 0, not 1.
  • Real operations: Real operations are performed only on real operands or combinations of real, integer, and logical operands. Any integer operands present are converted to real data type by giving each a fractional part equal to zero. The expression is then evaluated using real arithmetic. However, in the statement Y = (I/J)*X , an integer division operation is performed on I and J, and a real multiplication is performed on that result and X.
    If any operand is a higher-precision real (REAL(8) or REAL(16)) type, all other operands are converted to that higher-precision real type before the expression is evaluated.
    When a single-precision real operand is converted to a double-precision real operand, low-order binary digits are set to zero. This conversion does not increase accuracy; conversion of a decimal number does not produce a succession of decimal zeros. For example, a REAL variable having the value 0.3333333 is converted to approximately 0.3333333134651184D0 . It is not converted to either 0.3333333000000000D0 or 0.3333333333333333D0 .
  • Complex operations: In operations that contain any complex operands, integer operands are converted to real type, as previously described. The resulting single-precision or double-precision operand is designated as the real part of a complex number and the imaginary part is assigned a value of zero. The expression is then evaluated using complex arithmetic and the resulting value is of complex type. Operations involving a COMPLEX(4) or COMPLEX(8) operand and a DOUBLE PRECISION operand are performed as COMPLEX(8) operations; the DOUBLE PRECISION operand is not rounded.

These rules also generally apply to numeric operations in which one of the operands is a constant. However, if a real or complex constant is used in a higher-precision expression, additional precision will be retained for the constant. The effect is as if a DOUBLE PRECISION (REAL(8)) or REAL(16) representation of the constant were given. For example, the expression 1.0D0 + 0.3333333 is treated as if it is 1.0D0 + 0.3333333000000000D0 .

4.1.2 Character Expressions

A character expression consists of a character operator (//) that concatenates two operands of type character. The evaluation of a character expression produces a single value of that type.

The result of a character expression is a character string whose value is the value of the left character operand concatenated to the value of the right operand. The length of a character expression is the sum of the lengths of the values of the operands. For example, the value of the character expression 'AB'//'CDE' is 'ABCDE' , which has a length of five.

Parentheses do not affect the evaluation of a character expression; for example, the following character expressions are equivalent:


('ABC'//'DE')//'F'
'ABC'//('DE'//'F')
'ABC'//'DE'//'F'

Each of these expressions has the value ' ABCDEF ' .

If a character operand in a character expression contains blanks, the blanks are included in the value of the character expression. For example, 'ABC '//'D E'//'F ' has a value of 'ABC D EF ' .

4.1.3 Relational Expressions

A relational expression consists of two or more expressions whose values are compared to determine whether the relationship stated by the relational operator is satisfied. The following are relational operators:

Operator Relationship
.LT. or < Less than
.LE. or <= Less than or equal to
.EQ. or == Equal to
.NE. or /= Not equal to
.GT. or > Greater than
.GE. or >= Greater than or equal to

The result of the relational expression is .TRUE. if the relation specified by the operator is satisfied; the result is .FALSE. if the relation specified by the operator is not satisfied.

Relational operators are of equal precedence. Numeric operators and the character operator // have a higher precedence than relational operators.

In a numeric relational expression, the operands are numeric expressions. Consider the following example:


APPLE+PEACH > PEAR+ORANGE

This expression states that the sum of APPLE and PEACH is greater than the sum of PEAR and ORANGE. If this relationship is valid, the value of the expression is .TRUE.; if not, the value is .FALSE..

Operands of type complex can only be compared using the equal operator (== or .EQ.) or the not equal operator (/= or .NE.). Complex entities are equal if their corresponding real and imaginary parts are both equal.

In a character relational expression, the operands are character expressions. In character relational expressions, less than (< or .LT.) means the character value precedes in the ASCII collating sequence, and greater than (> or .GT.) means the character value follows in the ASCII collating sequence. For example:


'AB'//'ZZZ' .LT. 'CCCCC'

This expression states that ' ABZZZ ' is less than ' CCCCC ' . In this case, the relation specified by the operator is satisfied, so the result is .TRUE..

Character operands are compared one character at a time, in order, starting with the first character of each operand. If the two character operands are not the same length, the shorter one is padded on the right with blanks until the lengths are equal; for example:


'ABC' .EQ. 'ABC  '

'AB' .LT. 'C'

The first relational expression has the value .TRUE. even though the lengths of the expressions are not equal, and the second has the value .TRUE. even though ' AB ' is longer than ' C ' .

A relational expression can compare two numeric expressions of different data types. In this case, the value of the expression with the lower-ranking data type is converted to the higher-ranking data type before the comparison is made.

For More Information:

On the ranking of data types, see Section 4.1.1.2.

4.1.4 Logical Expressions

A logical expression consists of one or more logical operators and logical, numeric, or relational operands. The following are logical operators:

Operator Example Meaning
.AND. A .AND. B Logical conjunction: the expression is true if both A and B are true.
.OR. A .OR. B Logical disjunction (inclusive OR): the expression is true if either A, B, or both, are true.
.NEQV. A .NEQV. B Logical inequivalence (exclusive OR): the expression is true if either A or B is true, but false if both are true.
.XOR. A .XOR. B Same as .NEQV.
.EQV. A .EQV. B Logical equivalence: the expression is true if both A and B are true, or both are false.
.NOT. 1 .NOT. A Logical negation: the expression is true if A is false and false if A is true.

1.NOT. is a unary operator.

Periods cannot appear consecutively except when the second operator is .NOT. For example, the following logical expression is valid:


A+B/(A-1) .AND. .NOT. D+B/(D-1)

Data Types Resulting from Logical Operations

Logical operations on logical operands produce single logical values (.TRUE. or .FALSE.) of logical type.

Logical operations on integers produce single values of integer type. The operation is carried out bit-by-bit on corresponding bits of the internal (binary) representation of the integer operands.

Logical operations on a combination of integer and logical values also produce single values of integer type. The operation first converts logical values to integers, then operates as it does with integers.

Logical operations cannot be performed on other data types.

Evaluation of Logical Expressions

Logical expressions are evaluated according to the precedence of their operators. Consider the following expression:



A*B+C*ABC == X*Y+DM/ZZ .AND. .NOT. K*B > TT

This expression is evaluated in the following sequence:



(((A*B)+(C*ABC)) == ((X*Y)+(DM/ZZ))) .AND. (.NOT. ((K*B) > TT))

As with numeric expressions, you can use parentheses to alter the sequence of evaluation.

When operators have equal precedence, the compiler can evaluate them in any order, as long as the result is the same as the result gained by the algebraic left-to-right order of evaluation (except for exponentiation, which is evaluated from right to left).

You should not write logical expressions whose results might depend on the evaluation order of subexpressions. The compiler is free to evaluate subexpressions in any order. In the following example, either (A(I)+1.0) or B(I)*2.0 could be evaluated first:


(A(I)+1.0) .GT. B(I)*2.0

Some subexpressions might not be evaluated if the compiler can determine the result by testing other subexpressions in the logical expression. Consider the following expression:


A .AND. (F(X,Y) .GT. 2.0) .AND. B

If the compiler evaluates A first, and A is false, the compiler might determine that the expression is false and might not call the subprogram F(X,Y).

For More Information:

On the precedence of numeric, relational, and logical operators, see Section 4.1.6.


Previous Next Contents Index