PROGRAMMING IN
FORTRAN
Fourth Edition
Omer AkgirayPERMISSION TO COPY AND DISTRIBUTE:
This book may be copied and distributed in digital or printed form
provided that the front cover that contains the name of the author
and the title of the book is included with each copy. Individual
chapters may be copied and printed in the same way.
e-mail:
[email protected]49
CHAPTER 2: DECISION STRUCTURES
2.1 Logical Constants and Variables
There are only two logical constants. They are true and false, and are represented
in FORTRAN as . TRUE. and . FALSE., respectively. Note that the words TRUE and
FALSE are preceded and followed by periods. When logical data are printed, the
letters T and F, representing . TRUE. and . FALSE., respectively, are printed without
the enclosing periods. Storage locations which are used to store logical values which
can be varied are called logical variables. Logical variable names must be declared
by the type statement LOGICAL. For example,
LOGICAL A, MOON, GOOD
declares A, MOON, and GooD as logical variables. Examples of the use of logical
constants and variables will be given later in this chapter.
2.2 Relational Expressions and the Single-Alternative Decision Structure
FORTRAN provides a decision-making capability in the form of a construct known as
the block-1F structure. The simplest form of this structure is the single-alternative
decision form and has the following general format:
LF (logical expression) THEN
Task
ENDIF
A logical expression (sometimes also called a logical condition) is an expression
which is either true or false (i.e., . TRUE. of . FALSE.). When the block-IF structure
is executed, the logical expression is first evaluated. If the expression is true, then
the program statements that constitute Task are executed. If the /ogical expression is
false, then Task is skipped and execution continues with the first statement following
the ENDIF statement.
We shall first discuss a special class of logical expressions, namely relational
expressions. A relational expression consists of two arithmetic expressions
connected by a single relational operator. The following are the relational operators
used in FORTRAN:=
-EQ. equal to
-NE. not equal to
ST. greater than
-LT. less than
a. less than or equal to
GE. greater than or equal to
It should be noted that each relational operator has four characters, two letters
preceded and followed by a period’. Some examples of mathematical conditions and
their equivalent FORTRAN relational expressions are given below:
A
onto cards. As a result, all relational operators consisted of two letters enclosed between periods.51
Before FORTRAN 77, it was necessary to use a STOP statement somewhere
in the program (not necessarily at the end) to terminate execution. The END
statement was not an executable statement and its only function was to signal to the
compiler that there were no more lines to be compiled”. When the execution
sequence of the program statements is rather straightforward, it often happens that
execution is terminated at only one place, i.e. at the end of the program. In such a
case, before the advent of FORTRAN 77, one would have to place a STOP
statement just before the END statement. Although many FORTRAN programmers
still have the habit of placing a STOP statement just before the END statement of the
main program, the STOP statement is not necessary if it is immediately followed by
the END statement.
Note also that the END statement of a subprogram has the same effect as a
RETURN statement, whereas the END statement in the main program has the same
effect as a STOP statement.
Example 2.1:
Suppose we want to write a program that reads a number interactively, calculates the square
root of the number, and displays the result on the computer screen. The intrinsic function
SQRT will be used for this purpose. The square root of a negative real number, however, is not
defined. It would therefore be useful to detect a negative number and print an informative
error message when a negative number is entered by the user of our program.
PROGRAM SQROOT
HHS EEE S EIS ISSR SSE IESE SEI ESI SSSI BOE SEE I ISSIS ESTOS IO IIE
© Program to calculate the square root of a real number
C NUM: A real value entered by the user
SHEERS ESSE HE IIIS IO ESSE SSO ECE E I I ISIS ERITH ISO IASI ISIS IIIA
IMPLICIT NONE
REAL NUM
PRINT*, ‘Enter your number: '
READ*, NUM
IF (NUM.LT.0) THEN
PRINT*, ‘Square root of a negative number is not defined.'
STOP
ENDIF
PRINT*, 'Square root is', SQRT(NUM)
END
Two sample runs of the program are given below:
Enter your number: 4
Square root is 2.00000
Enter your number: -1
Square root of a negative number is not defined.
Fortran 90 allows the use of <, <=, >, >=, and /= instead of .LT., .LE., .GT., .GE., EQ., and .NE.,
respectively. Note that the older forms .LT., .LE. etc. are still valid in Fortran 90.
? Organick and Meissner, p.76,Ry!
The program first displays a prompting message, informing the user that a number is
to be entered. Once the value of NUM is read, it is compared with zero. Note that the relational
expression
NUM.LT.0
compares a real variable (NUM) with an integer constant (0 without a decimal point). This is
permissible because mixed-type expressions are allowed in FORTRAN 77°. The compiler
handles such a mixed-type logical expression as follows. The integer constant is first
converted to type real by appending a decimal point. Then comparison between two real
values are carried out.
If NuM is zero or positive, then the relational expression NUM.LT.O has the value
.FALSE., and the program execution continues with the statement immediately following the
ENDIF statement:
PRINT*, 'Square root is', SQRT (NUM)
The program execution is then terminated by the END statement. If, on the other hand, NuM is
negative, then the value of the relational expression NUM.LT.0 will be .TRUE., and the
statements within the block-IF structure are next executed. The first statement
PRINT*, "Square root of a negative number is not defined.'
gives information to the user about why the square root of the specified number cannot be
calculated. Next, the program execution is terminated by the stor statement. Notice that, in
this case, the PRINT statement that follows the ENDIF statement is never executed. This
example illustrates how the sTOP statement can be used to terminate the execution of a
program before reaching the END statement.
Although in this text we shall always indent the statements that constitute the
body (i.e., Task) of a block-IF structure, this is of course not required. It is, however,
a good practice to follow as it enhances the readability of programs. This point will
become more apparent as we start using more complicated contro! structures such
as the multiple-alternative decision structure (Section 2.3), and especially nested
block-1F statements (Section 2.6) and nested loops (Chapter 3).
2.3 The Multiple-Alternative Decision Structure
The double-alternative decision structure has the following general format:
IF (logical expression) THEN
Task
ELSE
False Task
ENDIF
The logical expression is first evaluated. If the expression is true, then the program
statements that constitute Task are executed and those that constitute False Task
are skipped. If the logical expression is false, then Task is skipped and False Task is
3 Expressions of the mixed-type were not permitted in standard FORTRAN 66. Be that as it may, most
of the compilers commercially available in early 1970s allowed mixed-type expressions (Organick and
Meissner, p.59 and p.276).53
executed. In either case, execution continues with the first statement following the
ENDIF statement.
Example 2.2:
In this example we look at a subprogram that determines if a given integer is even or odd.
Since there are only two possible answers (even and odd), it seems reasonable to implement
this subprogram as a logical function which can return two possible values (.TRUE. or
. FALSE.). Consider the following function which retums the logical value . TRUE. when the
input argument N is odd:
LOGICAL FUNCTION ODD (N)
OHS H SEES EES E GHEE SEES I BIOS OEE HEEHSEEISISSISIOBS HERE I SISOS ISG GEE
© Function returns .TRUE. if N is odd, returns .FALSE. otherwise
GOES SCS HO SUISSE SSIS SEE G EIS IIIS H EE SII IG ESOT TASTE I A ATI
IMPLICIT NONE
INTEGER N
IF(N/2*2 .EQ. N) THEN
ODD = .FALSE.
ELSE
ODD = .TRUE.
ENDIF
RETURN
END
Alternatively, one can implement a function named EVEN that returns . TRUE. when
N is even (make sure to do it). The following main program (which itself contains an example
of the block-IF construct) has been written to test FUNCTION ODD:
PROGRAM ODDNUM
© Driver routine for FUNCTION ODD
IMPLICIT NONE
INTEGER NUM
LOGICAL ODD
PRINT*, ‘Enter the number to be tested: '
READ*, NUM
IF (ODD (NUM) ) THEN
PRINT*, 'The number is odd.'
ELSE
PRINT*, 'The number is even.'
ENDIF
END
A sample program output follows:
Enter the number to be tested: 4
The number is even.
After the number (uM) has been read in, the block-1F statement is executed. The
first step is the evaluation of the logical expression of the block-IF structure. The logical
expression here consists of a single function reference, i.e. ODD (NUM). Control then passes
into the function and the statements within the function are executed. The dummy argument N
is assigned the value of the actual argument num. (Remember that there is name
independence between program units.) Next, the value of N/2*2 is compared with N. Let us
take a close look at this step of the function subprogram. In the arithmetic expression
N/2*2
division is carried out first, ie. the expression is equivalent to
(N/2)*234
Since both w and the constant 2 are integers, integer arithmetic is used in the evaluation of
this expression. In particular, any remainder resulting from the division of two integer values is
simply discarded. If is even, the remainder of the division process N/2 is zero, and N/2 is
exactly equal to half of N, and therefore N/2*2 is equal to N. When N is odd, however, the
remainder of the division is not zero and N/2 is less than half of n. For example, if N is 3, then
N/2 is 1 (which is less than 1.5) and N/2*2 has the value 2 which is different from N. Thus, if
the value of the relational expression
N/2*2.EQ.N
is TRUE., then N is even. Otherwise, N is odd. The name of the function is assigned the value
-TRUE. if N is odd; otherwise it is set equal to .FALSE.. Control is then retumed to the calling
(i.e. main) program. All of this happens during the evaluation of the logical condition of the
block-1F structure in the main program. If this logical expression evaluates to .TRUE., then the
string 'The number is odd. ' is displayed. Otherwise, the string 'The number is
even. ' is displayed.
The single-alternative and the double-alternative forms discussed earlier are
special cases of the multiple-alternative decision structure (also called block-IF).
The general form of the block-1F structure is as follows:
IF (logical expression;) THEN
Task,
ELSE IF (logical expression2) THEN
Task
ELSE IF (logical expression,) THEN
Task,
ELSE
False Task
ENDIF
The Jogical expression, is first evaluated. If it is true, then Task; is executed and all
the other tasks are skipped. If logical expression, is false, then Task; is skipped and
logical expression is next evaluated. Thus, logical expressiom, logical expression2,
etc. are evaluated until an expression, say /ogical expression,, that evaluates to true
is reached. In that case Task; is executed. If none of the conditions holds true, False
Task is evaluated. In all cases, execution is continued with the first statement
following ENDIF. If False Task is empty, that is, if there are no statements to be
executed when all the conditions (logical expression; through logical expressionn)
evaluate to false, then the word ELSE may be omitted.
Example
The sign function sgn(x) is commonly defined as follows:
1 if x is greater than zero or if xis zero
1 if xis strictly less than zero55
The implementations of the FORTRAN sign transfer functions IsIGN, DSIGN, and
SIGN are based on the above definition of the sign function. In particular, ISIGN(1,0) is
equal to 1 and SIGN(1.,0.) is 1., because sgn(0) = 1 according to its definition. Suppose a
certain application requires that we take sgn(0) to be zero. In such a case, we cannot directly
use the library functions in our computations. We can, however, implement our own sign
transfer function. Here is one way this can be done:
PROGRAM MYSIGN
© Main program to test ISIGN2
IMPLICIT NONE
INTEGER NUMBER, ISIGN2
PRINT*, ‘Please enter a number: '
READ*, NUMBER
PRINT*, ‘Sign =', ISIGN2(1, NUMBER)
END
c
INTEGER FUNCTION ISIGN2(M, N)
CHE BESS EEE EOS SSIS IOS BOS OE ESCH TETEEE ORCS ISOS ASSIS I IEE
C User-defined sign transfer function
© Works with integer arguments only
GES H SEIS SSS SE IS IIE BIOS ESCO EELS CIT GOCEE III ISI IR III
IMPLICIT NONE
INTEGER M, N
IF (N.LT.0) THEN
ISIGN2 = -ABS (M)
ELSE IF(N.EQ.0) THEN
ISIGN2 = 0
ELSE
ISIGN2 = ABS (M)
ENDIF
RETURN
END
Note that this function handles integer arguments only. You must write two other functions,
say DSIGN2 and SIGN2, to handle double precision and real arguments, respectively’.
Exercises:
4. The library function Mop returns the remainder of the division of its first argument by the
second. Modify FUNCTION ODD of Example 2.2 to employ MoD to determine if N is odd or not.
2. Insert the following statement just before the END statement in PROGRAM MYSIGN:
PRINT*, 'ISIGN(i,NUMBER) =', ISIGN(1,NUMBER)
Recompile and run the program with the following values: 1, 0, and -2. Compare the values
retumed by ISIGN with those calculated by ISIGN2
3. Write a program to read in three real numbers, and determine and display the largest of the
three numbers (without using library functions).
4. In Example 1.13 we studied a simple function for the calculation of cube root. The following
is a more generalized version of that function:
REAL FUNCTION CBRT (X)
HEH S HOSOI HEISE OS ECCS SSRISESEESSEE ESSE SESS G ONCE ITER IIIT I I
© Calculates cube root of real number X
GHC CUETO SESS OIE SITES SE HOS SSE HIEFE EI ISS IIS SO ETE IJ III:
* Recall that generic library functions such as SIGN, SORT, etc. can be used with different types of
arguments, It is not possible to define generic external functions in FORTRAN 77. Fortran 90 brings a
solution to this problem by allowing programmers to refer to two or more functions using the same
generic name (see Chapter 7),56
IMPLICIT NONE
) THEN
EXP (LOG (-X) /3.)
T.0.) THEN
EXP (LOG(X) /3.)
Note that the algebraic equality -¥/(-x) = 2x is utilized to handle negative values of x. Write
a main program to test this function. What happens if you use the expression x**(1./3) to
calculate the cube root of a negative number? (Try it.) Notice also how the zero argument
situation is handled. (Remember that logarithm of zero is not defined.)
2.4 Compound Logical Expressions
A relational expression is a special type of logical expression. Logical expressions
may also consist of logical constants (. TRUE. or . FALSE.) or logical variables used
by themselves. For example, if FOUND is a logical variable, then the statement
IF (FOUND) THEN
PRINT*, ‘Solution found.'
ELSE
PRINT*, 'Cannot find solution."
ENDIF
will print the statement solution found. if FOUND has the value . TRUE.. If, on the
other hand, FOUND has the value .FALSE. when this segment of the program is
being executed, the message printed willbe Cannot find solution..
Logical expressions more complex than the simpler expressions just
mentioned can be constructed using the following FORTRAN logical operators:
-AND. -OR. -NOT. -EQV. .NEQV.
Given any two logical expressions logexp7 and logexp2, we can form the following
compound logical expressions:
logexp1.AND.logexp2
logexp4.OoR.logexp2
.NoT.logexp7
logexp.EQVv.logexp2
logexp.NEQV.logexp2m3
It should be noted that the words AND, OR, NOT, EQV, and NEQV are preceded and
followed by periods. The values of these compound expressions depend on the
values of logexp7 and /ogexp2 and are as follows (T and F stand for . TRUE. and
. FALSE., respectively):
logexp1 logexp2 logexp1.AND.logexp2 _logexp7.oR.logexp2
T T T T
T E E a
EF T F T
E E E E
- NOT. is a unary operator that changes the value of any logical expression
from . TRUE. to . FALSE. or from . FALSE. to . TRUE.:
logexp1
T
-NOT.logexp4
J
The operators .EQV. and .NEQV. are used to test logical expressions for
equivalence and nonequivalence, respectively. For example, /ogexp7.£OV.logexp2
has the value . TRUE. if logexp7 and fogexp2 have the same value (both . FALSE.
orboth .TRUE.). The properties of these operators are summarized below:
logexp1 logexp2 logexp7.EQv.logexp2 _logexp7.NEQv.logexp2
T T T F
T E FE T
FE T E .
FE E Tr E
Note that the analogous relational operators .£Q. and .NE. are used to
compare arithmetic (integer, real, double precision, complex) and character data,
whereas .EQV. and .NEQV. are used to compare logical values. The latter two
operators are most often used to simplify the structure of logical expressions. The
following two expressions, for example, are equivalent in their effect:
(A.LE.B.AND.Y.GT.X)
A.LE.B .EQV. Y.GT.X
+OR.
(A.GT.B.AND.Y.LE.X)58
Assume that A, B, and c are real variables, NAME1 and NAME2 are of type
character and FLAG is of type logical. The following are valid logical expressions:
A.GT.0.0
(A.LE.B) «AND. (C.GT.1.)
FLAG
-NOT. FLAG
(A.LT.2.) OR. (.NOT. FLAG)
NAME1.NE.NAME2
Any combination of the above logical expressions using .AND. and .oR. are also
valid logical expressions. For example
((A.LT.2.).OR.(.NOT.FLAG)) .AND. (NAME1.NE.NAME2)
(A.GT.0.0) .AND. (.NOT.FLAG)
Similarly, any combination of the above expressions using .EQV. and .NEQV. are
valid logical expressions. For example
(NAMEL.NE.NAME2) .EQV. (.NOT.FLAG)
(((A.LT.2) .OR. (.NOT. FLAG) ) . AND. (NAME1.NE.NAME2)) .NEQV. (A.GT.0)
For clarity, extra parentheses and blanks have been used in some of the
above expressions. For example, the following three expressions have the same
meaning for the compiler:
(A.LT.2.) .OR. (.NOT.FLAG)
(A.LT.2.).OR. (.NOT. FLAG)
A.LT.2..OR..NOT. FLAG
In forming complicated logical expressions, the following hierarchy of
operations (precedence of operators) should be remembered:
1. All subexpressions within parentheses are evaluated first. In the case of
nested parenthesized subexpressions, the innermost subexpression is
evaluated first.
2. A parenthesis-free subexpression is evaluated using the following hierarchy:
i) Arithmetic operations
a) First precedence: ”
b) Second precedence: *,/
ce) Third precedence: +-
ii) Relational operators (.£Q., .NE., .LT., .GT., .GE., .LE.)
iii) Logical operators
a) First precedence: NOT.=
b) Second precedence: .AND.
c) Third precedence: OR.
d) Last precedence: .EQV., .NEQV.
3. Operators within the same parenthesis-free subexpression and at the same
level of hierarchy (such as .£Q. and .LE.) are evaluated from left to right.
We see that arithmetic operations are performed first. Relational expressions
are next evaluated before compound logical expressions. Among the six relational
operators, there is no priority and relational operations are carried out from left to
right. When in doubt, it is better to use parentheses to explicitly specify the desired
grouping of operands and operators. Furthermore, it is recommended that extra
parentheses and blank spaces be used when such usage enhances the clarity and
legibility of a program. For example, assuming x, Y, 2, A, B, and c are real
variables, the expression
(A.LT.B) .OR. ( (A-EQ.C) -AND. (B.NE. (X+Y¥/Z)) )
and its equivalent
A.LT.B .OR. (A.EQ.C .AND. B.NE. (X+¥/Z))
are easier to understand than the (also equivalent and correct) statement
A.LT.B.OR.A.EQ.C.AND.B.NE.X+¥/Z
Example 2.4:
In this example we will look at a function subprogram that can be used to determine if a given
year is a leap year or not. Remember that a leap year is a year containing 366 days with
February 29 as the extra day. The function is named LEAPYR, and is a logical function that
returns . TRUE. if the given year is a leap year; returns . FALSE. otherwise.
Agiven year is a leap year if it is evenly divisible by 4 and not by 100, or it is evenly
divisible by 400. For example, 1999 is not a leap year (1999 is not evenly divisible by 4),
whereas 2000 is a leap year (evenly divisible by 400). Similarly, year 1900 is not a leap year
(it is evenly divisible by 100 but not by 400). Notice how a compound logical expression is
used in the program to implement the definition of a leap year.
LOGICAL FUNCTION LEAPYR (YEAR)
OHHH SEES EEE EHS S SI ISG SGI TIC ONOS SSSI TESS ISIS TCG I
C Returns .TRUE. if YEAR is a leap year; returns .FALSE. otherwise
GHEE USES IEC G HUES UB SHOOTS SSIES SIS I OSIS DIES IES OEIGE ITE IASI
IMPLICIT NONE
INTEGER YEAR, REM4, REM100, REM400
REM4 = MOD(YEAR, 4)
REMLOO = MOD(YEAR, 100)
REM400 = MOD(YEAR, 400)
TE( (REM4.EQ.0 .AND. REMIO0.NE.0) .OR. REM400.5Q.0) THEN
LEAPYR = .TRUE.
ELSE
LEAPYR = . FALSE.
ENDIF
RETURN
END60
The function employs the variables named REM4, REM100, and REM400 to store the
computed remainders of the year after division by 4, 100, and 400 respectively. The extra
parentheses around the expression REM4.EQ.0 .AND. REM1OO.NE.0 are actually not
necessary since .anp. has higher precedence than .or.. Similarly, extra blanks are used
within the compound logical expression to improve readability. The following version,
therefore, would also be perfectly valid (although less legible):
TF (REM4.EQ.0.AND.REM100.NE.0.OR.REM400.EQ.0) THEN
Note that the following version would also give correct results in this case (why?):
IE (REM4.EQ.0 .AND. (REM1O0.NE.0 .OR. REM400.8Q.0) )THEN
The following is a main program that can be used to test FUNCTION LEAPYR:
PROGRAM LEAP
IMPLICIT NONE
INTEGER YEAR
LOGICAL LEAPYR
PRINT*, ‘Enter the year to be tested: '
READ*, YEAR
IF (LEAPYR (YEAR) ) THEN
PRINT*, 'It is a leap year.'
ELSE
PRINT*, 'No, it is not a leap year.'
ENDIF
END
Example 2.
This example provides another illustration of the use of compound logical expressions
constructed using the operators .AND. and .OR.
PROGRAM LETGRD
¢ Program determines and prints the letter grade
€ corresponding to a score between 0 and 100.
IMPLICIT NONE
INTEGER SCORE
CHARACTER*1 GRADE, LETTER
PRINT*, 'Enter the score (between 0 and 100):
READ*, SCORE
LETTER = GRADE (SCORE)
IF(LETTER.EQ.'*') THEN
PRINT 1, 'Score entered’, SCORE, 'is out of range:'
PRINT 1, 'You must enter a value between 0 and 100.’
ELSE
PRINT 1, ‘Score =', SCORE, '=> Letter Grade =', LETTER
ENDIF
1 FORMAT(1X, A, :, 1X, 14, 1X, A, :, 1X, A)
END
CHARACTER*1 FUNCTION GRADE (SCORE)
OSE C CEES ESE SESE O SSO ICI T EIS UISSISSIORC TEE EEEEEESIISISS II ISSO IO
© Returns letter grades ‘A', 'B', 'C', 'D', or 'F' for specified
C SCORE between 0 and 100. Returns '*' if SCORE is out of range.
HSCEI IE SIE ESSE IIT SO SSRN ICUS E EIEIO RIS HEE IS GOO I TAI II I
IMPLICIT NONE
INTEGER SCORE
IF(SCORE.LT.O .OR. SCORE.GT.100) THEN
GRADE = '*!
ELSE IF(SCORE.GE.90 .AND, SCORE.LE.100) THEN
GRADE = 'A'
ELSE IF(SCORE.GE.80 .AND. SCORE.LE. 89) THEN
GRADE = 'B!
ELSE IF (SCORE.GE.70 .AND. SCORE.LE. 79) THEN
GRADE = 'C!ELSE IF(SCORE.GE.60 .AND. SCORE.LE.
GRADE = 'D!
ELSE IF(SCORE.GE. 0 .AND. SCORE.LE.
GRADE = 'F!
ENDIF
RETURN
END
61
69) THEN
59) THEN
It may be noted that, the block-1F structure within the function could be replaced by
IF(SCORE.LT.O
GRADE = '*!
ELSE IF (SCORE.GE.90) THEN
GRADE = 'At
ELSE IF (SCORE.GE.80) THEN
GRADE = 'B!
ELSE IF (SCORE.GE.70) THEN
GRADE = 'C
ELSE IF (SCORE.GE.60) THEN
GRADE = 'D!
ELSE
GRADE = 'F!
ENDIF
-OR. SCORE.GT.100) THEN
This version is simpler (requires less typing). It was decided, however, that explicitly
specifying the range of scores that gets each letter grade made the logic of the program more
easily understandable.
Example 2.
Logical expressions are most frequently used to specify conditions in decision statements, and
(as we shall see in the next chapter) in DO WHILE loops. They may also be used in
assignment statements involving logical variables. This is usually done to simplify the listing
of conditions in a block-1F structure. An example is provided below.
PROGRAM ORDER
Cc Reads in three numbers and determines their relative sizes
C >= means greater than or equal to
© > means strictly greater than
IMPLICIT NONE
REAL X, Y, Z
LOGICAL Ll, L2, 13
PRINT*, ‘Enter X, Y, 2: '
READ*, X, ¥, Z
Ll = X.GE.Y
L2 = X.GE.Z
L3 = ¥.GE.Z
TE(L1 .AND. L3)THEN
PRINT*, 'X >= Y >= 2!
ELSE IF(L1 .AND. 12) THEN
c L1.AND.L2 is .TRUE., but L1.AND.13 is . FALSE.
c This can happen only if L3 is .FALSE, whereas L1 and L2 are .TRUE.
PRINI*, 'X >= Z > ¥!
BLSE IF (L1) THEN
c Ll is .TRUE., but both L1.AND.L2 and L1.AND.L3 are .FALSE.
c This can happen only if both L2 and L3 are .FALSE
PRINT*, 'Z > X >= Y!
ELSE IF (L2) THEN
c L2 is .TRUE., but Ll is .FALSE.
PRINT, '¥ > X >= 2!
ELSE IF(L3) THEN
G 13 is .TRUE., Ll and L2 are .FALSE.
PRINT*, '¥ >= Z > x!
ELSE
c Ll, L2 and L3 are all . FALSE.
PRINT*, 'Z > Y > X'
ENDIF
END