sum / product of elements (sum(a, dim=), sum(a, mask=))
maxval / minval
largest / smallest element
maxloc / minloc
position of the max / min (use dim=1 for a scalar on rank-1)
count(mask)
how many elements satisfy a logical condition
matmul(A, B)
the matrix product ($C_{ij}=\sum_k A_{ik}B_{kj}$)
dot_product(x, y)
the scalar $\sum_i x_i y_i$
transpose(A)
rows ↔ columns
reshape(src, shp[, order=])
reflow a 1-D constructor into higher rank
spread(src, dim, ncopies)
replicate an array along a new dimension
merge(t, f, mask)
elementwise pick between two arrays
Which construct, when
You want to…
Reach for
add / scale / transform a whole array
whole-array op: c = a + b, y = sqrt(x)
the elementwise product
a * b
the matrix product
matmul(a, b) (never a * b)
a running total / extreme / tally
sum / maxval / count
operate on only some elements
where (mask) …, or a masked sum/count
size an array at run time
allocatable + allocate
Pitfalls
One-based, not zero-based. The first element is a(1); there is no a(0) by default. Translating a C
for (i=0; i<n; i++) gives do i = 1, n. Compile with -fcheck=all to catch out-of-bounds.
a * b is elementwise, not matrix multiply. For linear algebra name it: matmul, dot_product.
Conformance is enforced.a(3) = b(4) will not compile; whole-array ops need matching shapes.
Integer reductions truncate on divide.sum(k)/size(k) on an integer array does integer division; use
sum(k)/real(size(k), dp) for a true mean (the Chapter 3 trap, on arrays).
Column-major loop order. The inner loop runs over the first index. Wrong order compiles, gives the
right answer, and can be ~10× slower.
The one rule to memorize
Fortran is COLUMN-MAJOR: the first index varies fastest in memory.
=> store column by column; put the FIRST index on the INNER loop.
do j = 1, n ! outer: columns
do i = 1, n ! inner: rows <-- with the memory grain (FAST)
a(i, j) = ...
end do
end do
Numbers worth carrying
A real(dp) value is 8 bytes; a cache line (~64 bytes) holds 8 of them.
An $n \times n$ matmul costs about $2n^3$ flops — fine small, call LAPACK large (Ch. 21).
Loop-order (column-major vs against-the-grain) is an illustrative ~10×, measured in Ch. 27.
Project piece added this chapter
The heat solver's temperature field becomes a 2D allocatable array u(:,:), and its Laplacian is
one whole-array statement of shifted sections: