Arrays, sections and sum
One name for many values: declaring an array, filling it, taking a section out of it, and letting the built-in functions do the counting, summing and searching.
One name for a run of values
An array is declared with its size: integer, dimension(5) :: xs, or the shorter integer :: xs(5) that means the same thing. The first element is xs(1), not xs(0) — Fortran counts from one, and after a few hours it is the most natural thing in the world.
Nothing checks an index at run time by default. Reading xs(6) from a five-element array reads whatever happens to be next in memory; writing it corrupts something else. That speed is the reason Fortran is used for large numerical work, and the reason array code deserves a second look before it is trusted.
Filling an array, and doing it all at once
The square brackets build a value from a list: xs = [4, 8, 15, 16, 23]. Assigning a single value to the whole array is allowed (xs = 0) and sets every element, which is the fastest way to clear it.
Arithmetic applies to whole arrays element by element. 2 * xs is an array of the same size with every value doubled; xs + ys adds element by element; xs ** 2 squares each one. No loop is needed, and this is not a convenience feature bolted on — expressing the operation on the whole array is what lets the compiler generate fast code.
An array constructor can be built with an implied loop: [(i * i, i = 1, 5)] gives the first five squares. The brackets are the constructor and the parentheses hold the loop, which is the standard way to fill an array from a formula without a separate do block. The result has a known length, so it can be assigned to a fixed-size array directly.
Sections and the intrinsics
xs(2:4) is a section: elements 2, 3 and 4, in order. It can be printed, summed, or passed to a procedure that expects a smaller array — which is how a program works on part of a table without copying it into a new variable.
Fortran ships a large set of array functions, and four of them remove most hand-written loops: size, sum, maxval and minval. sum(xs(2:4)) totals the middle of the array, maxval(xs) finds the largest, and size(xs) is the length — better than the literal 5, because it stays right when the declaration changes.
A section keeps the rank of the array. xs(2:4) is still a one-dimensional array of three elements, not a scalar, so it can be passed to a procedure that expects an array. xs(2) is the scalar at one position, and the two are not interchangeable even when the section happens to hold one element.
A small table of readings
integer, dimension(5) :: xs
xs = [4, 8, 15, 16, 23]
print *, xs(1), xs(5) ! first and last
print *, xs ! the whole array
print *, xs(2:4) ! 8 15 16
print *, sum(xs) ! 66
print *, maxval(xs) ! 23
xs = 0 ! every elementHow the values are laid out
An array occupies one contiguous block of memory, and Fortran stores it in column-major order: for a(3, 2), the three values of the first column come first, then the three of the second. That is why a nested loop over a matrix should run the first index in the inner loop — the pass that walks adjacent memory is the fast one, and the difference grows with the size of the array.
The declaration fixes the shape, and the shape is part of every whole-array operation. xs + ys requires the same number of elements; if they differ, the compiler stops. A section such as xs(2:4) names part of the array, so it can be printed, summed, or passed to a procedure that declares a smaller assumed-shape argument — while assigning it to another array copies the values across.
where applies a mask to a whole array: where (xs > 0) xs = 0 replaces every positive element and leaves the rest alone. It is the array form of an if, and like the other whole-array operations it says what to do to the data rather than how to walk it.
Three array mistakes are worth memorising. xs(0) is not the first element — Fortran counts from one, and index zero is out of bounds like any other. Assigning a five-element constructor to a four-element array is a compile error, not a resize. And an array that is declared but never filled holds whatever was in memory, so sum(xs) can be a large number with no warning at all.
Try these next
- Print
lbound(xs)andubound(xs)and confirm they are 1 and 5. - Use
maxlocto find the position of the largest value, then print that element. - Print
xs(5:1:-1)and explain the order in one sentence.
Print it, slice it, sum it
Run it and match each line to the statement that printed it. Then add a sixth value to xs, declare the array with dimension(6), and see which numbers change.
Stride, reverse and where the largest lives
Run it and match each line to the statement that produced it. Then add a seventh value, change the declaration to 7, and find every answer that changed.
Array bounds are not checked unless you ask for it. A program that reads one element past the end is legal to compile and may look right for months. Keep the loop bound as size(xs) and let the compiler keep the count for you.
Check what you learned
One question at a time. A wrong answer explains itself — take another go.
Part 1 of 5
Which element does xs(1) refer to?
