Self-Assessment Quiz: FORTRAN 77 to Modern Fortran
Twenty questions to confirm you can reach for the right modern construct on sight. Aim for 16 or more. Answers and a topic map are at the end — try the whole quiz first, and predict every "what prints" by hand. This is a reference chapter, so most questions are lookups: if you find yourself deriving a mapping from scratch, that is the signal to reread the relevant §.
Question 1
The single most valuable translation when modernizing legacy Fortran — because it ends an entire class of
silent bugs — is:
- A. .LT. → <
- B. COMMON → module
- C. fixed-form → free-form
- D. DATA → initializer
Question 2
A FORTRAN 77 EQUIVALENCE (X, IX) used to inspect the bit pattern of the real X is best replaced by:
- A. a derived type
- B. a separate allocatable array
- C. the intrinsic transfer(x, mold)
- D. a pointer
Question 3
EQUIVALENCE was used in old code for three different jobs. Which pairing of job → modern replacement is
wrong?
- A. save memory by overlaying scratch → separate allocatable arrays
- B. reinterpret bits → transfer
- C. name the fields of a storage block → a derived type
- D. save memory by overlaying scratch → transfer
Question 4
A local variable declared real(dp) :: total = 0.0_dp inside a subroutine that is called repeatedly:
- A. is reset to zero on every call
- B. is initialized once and keeps its value between calls (implicit SAVE)
- C. is a compile error
- D. is undefined on the second call
Question 5
The FORTRAN 77 backward GO TO that repeats a block of code translates most directly to:
- A. select case
- B. cycle
- C. a do ... end do loop with exit
- D. error stop
Question 6
A computed GO TO (10, 20, 30), K is the exact structured equivalent of:
- A. an arithmetic IF
- B. select case (k) with case default
- C. a do while
- D. a nested if on k's sign
Question 7
The three-way arithmetic IF (X) 10, 20, 30 branches to label 20 when:
- A. X is negative
- B. X is positive
- C. X is exactly zero
- D. X is NaN
Question 8
When you translate IF (RESID) ... on a real(dp) residual, the fragile branch is the one testing
resid == 0.0_dp because:
- A. equality is slower than inequality
- B. floating-point results almost never land on exactly zero, so the branch rarely fires
- C. real(dp) cannot represent zero
- D. the compiler forbids comparing reals
Question 9
Statement functions (e.g. SQ(X) = X*X) in modern Fortran are:
- A. still recommended for one-liners
- B. removed from the current standard; translate them to internal procedures
- C. faster than internal functions
- D. only allowed inside modules
Question 10
The modern replacement for a statement function is an internal (or module) function that is typically marked:
- A. recursive
- B. elemental always
- C. pure
- D. external
Question 11
An assumed-size dummy argument REAL A(*) becomes, in modern Fortran, the assumed-shape:
- A. real(dp) :: a(n)
- B. real(dp) :: a(:)
- C. real(dp) :: a(*)
- D. real(dp) :: a(100)
Question 12
Compared with REAL T(NX, *), the modern real(dp) :: t(:,:) removes the need to pass — and the chance to
get wrong — the:
- A. array's element type
- B. array's leading dimension / sizes
- C. array's intent
- D. array's kind
Question 13
In FORTRAN 77 a dummy argument had no intent, so it behaved effectively as:
- A. intent(in)
- B. intent(out)
- C. intent(inout)
- D. a parameter
Question 14
Converting fixed-form to free-form is best described as: - A. a correctness fix that eliminates bugs - B. a style change; fixed-form is still legal Fortran - C. required to compile any modern code - D. only possible with a special compiler flag
Question 15
Converting implicit typing to implicit none + declarations is best described as:
- A. a style change with no effect on correctness
- B. a correctness fix: it catches a mistyped name that implicit typing turns into a silent new variable
- C. a performance optimization
- D. purely cosmetic
Question 16
In fixed-form source, a non-blank character in column 6 means the line is: - A. a comment - B. a statement label - C. a continuation of the previous statement - D. ignored
Question 17
Which relational translation is incorrect?
- A. .NE. → /=
- B. .GE. → >=
- C. .EQ. → =
- D. .LT. → <
Question 18
What does this modern fragment print?
integer :: k = 2
select case (k)
case (1); print *, 'one'
case (2); print *, 'two'
case default; print *, 'other'
end select
- A.
one - B.
two - C.
other - D. nothing
Question 19
A modernization keeps a GO TO-style convergence loop's first clause (diff > tol) but drops its second
(iter < maxit). The risk is:
- A. the loop never executes
- B. the loop can run forever if the problem never converges
- C. a compile error
- D. slower convergence
Question 20
What does this print, and why? (The plate is 3×3, top edge hot.)
real(dp) :: t(3,3)
t = 0.0_dp
t(:,3) = 100.0_dp
t(2,2) = 0.25_dp*(t(1,2) + t(3,2) + t(2,1) + t(2,3))
print '(f6.2)', t(2,2)
- A.
0.00 - B.
25.00 - C.
100.00 - D.
50.00
Answer Key
| Q | Ans | Why |
|---|---|---|
| 1 | B | COMMON → module ends the "two routines disagree about the shared memory" bug class. |
| 2 | C | transfer(x, mold) reinterprets bits explicitly, with no lasting alias. |
| 3 | D | Memory-saving overlays become separate allocatable arrays, not transfer. |
| 4 | B | A declaration-initializer gives a local variable implicit SAVE: initialized once. |
| 5 | C | A backward GO TO is a loop; do ... end do + exit is the direct form. |
| 6 | B | A computed GOTO is a multi-way integer branch — exactly select case. |
| 7 | C | Arithmetic IF sends an exact zero to the middle label. |
| 8 | B | Real results rarely equal 0.0 exactly, so the exact-zero branch is effectively dead. |
| 9 | B | Statement functions are removed from the current standard; translate them. |
| 10 | C | A side-effect-free helper is pure, which licenses inlining/reordering. |
| 11 | B | a(:) is assumed-shape and carries its own extent. |
| 12 | B | Assumed-shape removes the passed leading dimension / sizes and the chance to mis-pass them. |
| 13 | C | With no intent, a dummy could be read and written — effectively inout. |
| 14 | B | Free-form is preferred style, but fixed-form remains legal. |
| 15 | B | implicit none turns a silent typo-variable into a compile error. |
| 16 | C | Column 6 non-blank = continuation of the previous line. |
| 17 | C | .EQ. → == (not =, which is assignment). |
| 18 | B | k == 2 selects case (2) → two. |
| 19 | B | Without the iteration cap, a non-converging problem loops forever. |
| 20 | B | 0.25*(0 + 0 + 0 + 100) = 25.00; the interior cell's four neighbours are the fixed edges. |
Topics to review by question
- Q1–4 → §19.1 (
COMMON→ module;EQUIVALENCE→transfer/derived type;DATA→ initializer; implicitSAVE). - Q5–8 → §19.2 (
GOTO/computedGOTO/arithmeticIF→do/exit/select case/if). - Q9–13 → §19.3 (statement function → internal
pureprocedure; assumed-size → assumed-shape;intent). - Q14–17 → §19.4 (fixed → free-form; implicit typing →
implicit none; relational operators). - Q18 → §19.2 (
select case); Q19 → §19.2 (translate every clause of aGOTOcondition). - Q20 → §19.2 (the Jacobi four-neighbour update, worked on a small 3×3 instance).
Scored below 16? The two highest-value sections to reread are §19.1 (storage — the COMMON and EQUIVALENCE
moves you will use most) and §19.2 (control flow — where "translate every clause" prevents the infinite-loop
bug). Both reward a second pass.