Exercises: Fortran 2023 and Beyond
This is a forward-looking chapter, so its exercises mix three flavours: prediction (what does this print, by hand), judgement (is this feature usable today, and how do you keep code portable while it is not), and research/design (read the standard's status, sketch a future-facing API, propose a feature). Because several 2023 constructs may not compile on the gfortran you have, many "port it" and "modernize it" problems ask you to write the portable version and describe the 2023 version — the same discipline the chapter practices. When a problem depends on your specific compiler or on the live fortran-lang site, it says so, and the appendix gives a model answer rather than one right answer.
Difficulty: ⭐ warm-up · ⭐⭐ standard · ⭐⭐⭐ deeper. Solutions: worked solutions to the daggered (†)
and odd-numbered problems are in appendices/answers-to-selected.md; the compilable ones are in
code/exercise-solutions.f90. Try every problem before you look.
A note on running code. Some problems ask you to build or run something — do it, ideally in the fortran-lang Playground or LFortran so you can try the new tools too. The book's no-execution policy is a discipline for the author, not a rule for you: predict the output first, then check.
Part A — Concept recall (⭐)
39.1† In one sentence, state the single behavioural difference between the merge intrinsic and a
Fortran 2023 conditional expression ( cond ? a : b ), and give one situation where that difference is not
merely stylistic but changes whether a program is correct.
39.2 Name the two committees that govern Fortran and describe, in a phrase each, what each is responsible for.
39.3† Fortran almost never deletes a feature; it marks the tired ones "obsolescent" instead. Give the one-word reason (the value the committee is protecting) and name a still-standard feature from Part IV that this policy keeps alive.
39.4 What can LFortran do that gfortran cannot, and what is the honest caveat about using LFortran for a large production code today?
Part B — Type, compile, and run (predict the output first) (⭐/⭐⭐)
39.5† (compilable — code/exercise-solutions.f90) Without running it, write the exact output of this
program, then check. The values are the same whether you use sind or the pi/180 conversion.
program p
use, intrinsic :: iso_fortran_env, only: dp => real64
implicit none
real(dp), parameter :: pi = 3.14159265358979_dp
integer :: k
integer, parameter :: deg(5) = [0, 30, 45, 60, 90]
do k = 1, 5
print '(a, i2, a, f8.5)', ' sind(', deg(k), ') = ', &
sin(real(deg(k), dp) * pi / 180.0_dp)
end do
end program p
39.6 For a = 2.0_dp and b = 9.0_dp, what does merge(a, b, a < b) return? What does
merge(a, b, a > b) return? State the rule you used.
39.7† Predict the five numbers printed by code/project-checkpoint.f90 (the half-sine hot edge for
nx = 5, t_hot = 100). You should be able to do the two nonzero interior values from memory of
sind(45°).
39.8 What does this print, and why is the case default never reached here?
integer, parameter :: bc_neumann = 2
integer :: bc = bc_neumann
select case (bc)
case (1); print *, 'Dirichlet'
case (2); print *, 'Neumann'
case default; print *, 'unknown'
end select
Part C — Port it (⭐⭐)
39.9† (compilable) Port this Python to portable Fortran (an explicit if/else), and note in a comment
what the equivalent Fortran 2023 conditional expression would look like:
y = a if x > 0 else -a
39.10 NumPy's np.where(mask, a, b) chooses element-wise between arrays a and b. Which existing
Fortran intrinsic is its closest match, and what is the one caveat you must remember about that intrinsic
that np.where shares (hint: both evaluate what)?
39.11† Rewrite this radians-based line using a Fortran 2023 degree intrinsic, and give the portable fallback beside it:
real(dp) :: heading = 30.0_dp ! degrees
real(dp) :: north_component = cos(heading * pi / 180.0_dp)
Part D — Find the bug (⭐⭐)
39.12 A colleague writes root = merge(sqrt(v), 0.0_dp, v >= 0.0_dp) to "avoid the square root of a
negative." Explain precisely why this does not protect against v < 0, and give both the portable fix and
the Fortran 2023 fix.
39.13† Another colleague pastes y = ( a > b ? a : b ) into a file and compiles with an older gfortran;
it fails with a syntax error. They conclude "Fortran 2023 is broken." What is actually wrong, and what are
the two honest ways forward?
39.14 This "enum" does not stop a real bug. Show an assignment that is nonsense but that the compiler accepts without complaint, and name the Fortran 2023 facility that would reject it.
integer, parameter :: red = 1, green = 2, blue = 3
integer, parameter :: mon = 1, tue = 2, wed = 3
integer :: colour
39.15† Given the two integer-parameter sets in 39.14, write a comparison that is type-nonsense yet
compiles and even evaluates to .true.. Explain what a real enumeration type buys you here.
Part E — Modernize it (⭐⭐)
39.16 This fragment converts degrees four times, and one conversion has a typo (108 instead of 180).
Rewrite it with degree intrinsics so the bug becomes impossible, and say why the modern form is safer.
sx = sin(ax * 3.14159265_dp / 180.0_dp)
sy = sin(ay * 3.14159265_dp / 180.0_dp)
cx = cos(ax * 3.14159265_dp / 108.0_dp) ! <-- typo
cy = cos(ay * 3.14159265_dp / 180.0_dp)
39.17† Modernize this magic-number boundary test into named constants (the portable idiom), then describe in one sentence how a Fortran 2023 enumeration type would improve it further:
if (bc == 1) then
u(1) = t_fixed
else if (bc == 2) then
u(1) = u(2) ! zero-flux
end if
Part F — Design it (extend the heat solver) (⭐⭐/⭐⭐⭐)
39.18 Sketch a boundary-selection expression for the solver that uses a Fortran 2023 conditional
expression to pick the edge temperature — t = ( on_hot_edge ? t_hot : t_cold ) — and write the portable
fallback you would ship as the default. Explain why you keep the fallback.
39.19† (compilable) Write a function bc_name(code) that maps boundary-condition codes 1, 2, 3 to
'Dirichlet', 'Neumann', 'periodic' and anything else to 'unknown', returning a deferred-length
string. Drive it over [1, 2, 3, 9].
39.20 Design (do not fully implement) a small solver-configuration API in which the time-stepping scheme and the boundary condition are each an enumeration type rather than an integer. List the enumerators you would define, and add a one-line honesty note about compiler support and a portable fallback.
39.21† (compilable) Generalize the half-sine hot edge to nx = 9 and print all nine temperatures.
Confirm by hand that the profile is symmetric and peaks at the centre cell.
Part G — Back of the envelope & interleaved (⭐⭐/⭐⭐⭐)
39.22 Fortran revisions have appeared roughly every five years (2003, 2008/10, 2018, 2023). Estimate the years of the next two revisions, then state two honest caveats about that estimate.
39.23† (interleave — Chapter 10) The book tells you to keep class out of a hot loop. What is the
run-time cost that motivates this rule, and how would the planned generics facility give you flexibility
over types without paying that cost?
39.24 (interleave — Chapter 32) In a coarray program, why must a read of a[q] be ordered against
remote writes with sync all? Then explain what a do concurrent (...) reduce(+:s) loop has conceptually in
common with co_sum.
39.25† (interleave — Chapter 16) Write the fpm.toml dependency line that adds stdlib to a project,
and explain in one sentence why use stdlib_stats fails under a bare gfortran file.f90 command.
39.26 (interleave — Chapters 5 & 29) You need b = a where a > 0 and b = 0 elsewhere, over a whole
array. Give the idiomatic Fortran (where), and explain why a scalar conditional expression ( a > 0 ? a :
0 ) is not a drop-in replacement for whole-array masking.
39.27† (research — model answer) Find out which Fortran 2023 features your installed compiler supports (for gfortran, its release notes / "Fortran 2023 status" page). Write down three features it has and two it does not, dated, so you can revisit as it improves.
39.28 (reflection — open-ended) Propose one feature you would like Fortran to add. Write a two-paragraph "paper": the problem it solves, a sketch of the syntax, and one interaction with an existing feature the committee would worry about. This is exactly how the process in §39.2 begins.
Solutions to the odd-numbered and † problems are in appendices/answers-to-selected.md; compilable
solutions for 39.5, 39.9, 39.19, and 39.21 are in code/exercise-solutions.f90. Predict every output by hand
first — then, for the new features, try them in the Playground or LFortran and watch the tooling work.