ZetCode

Fortran array intrinsics

last modified November 14, 2026

Fortran ships with a set of intrinsic functions that treat a whole array as one value. Some of them reduce an array to a scalar, such as sum and maxval; others return the position of a value, such as maxloc and findloc; and a third group rearranges arrays, such as pack, unpack and spread. A logical mask selects which elements take part in an operation. Using these functions instead of hand-written loops makes the intent clear and lets the compiler vectorise the work.

Sums and products

sum adds the elements of an array and product multiplies them, both returning a scalar when no dimension is given. With the dim argument they reduce along one dimension and return an array of one rank less: sum(m, dim=1) adds down the columns of a matrix, and sum(m, dim=2) adds across its rows. minval and maxval work the same way and return the smallest and largest values.

i1.f90
program i1
    implicit none
    integer :: a(5)
    integer :: m(2, 3)

    a = [4, 8, 15, 16, 23]
    m = reshape([1, 2, 3, 4, 5, 6], [2, 3])

    print *, 'sum:    ', sum(a)
    print *, 'product:', product(a(1:4))
    print *, 'minval: ', minval(a)
    print *, 'maxval: ', maxval(a)
    print *, 'sum of m:       ', sum(m)
    print *, 'sum along dim 1:', sum(m, dim=1)
    print *, 'sum along dim 2:', sum(m, dim=2)
end program i1

The five values add to 66, and the product of the first four is 7680. The smallest value is 4 and the largest is 23. The matrix holds the numbers 1 to 6, so its total is 21. Summing along dimension 1 gives one result per column, 3, 7 and 11, and summing along dimension 2 gives one result per row, 9 and 12.

$ gfortran i1.f90 -o i1
$ ./i1
 sum:              66
 product:        7680
 minval:            4
 maxval:           23
 sum of m:                 21
 sum along dim 1:           3           7          11
 sum along dim 2:           9          12

Locations of extremes

minloc and maxloc return the subscripts of the smallest and largest element instead of the values. For a rank-one array the result is a one-element array, and with dim it becomes an array of the positions along that dimension. findloc searches for a given value and returns its first position, or zero when the value is absent. All three count from the declared lower bound, which matters when the array does not start at 1.

i2.f90
program i2
    implicit none
    integer :: a(6)
    integer :: m(2, 3)

    a = [7, 3, 9, 3, 9, 1]
    m = reshape([5, 2, 8, 1, 6, 4], [2, 3])

    print *, 'minloc:', minloc(a)
    print *, 'maxloc:', maxloc(a)
    print *, 'findloc 9:', findloc(a, 9)
    print *, 'findloc 5:', findloc(a, 5)
    print *, 'maxloc of m:      ', maxloc(m)
    print *, 'maxloc dim 1:     ', maxloc(m, dim=1)
    print *, 'maxloc dim 2:     ', maxloc(m, dim=2)
end program i2

The smallest value in a is 1, at position 6, and the largest is 9, which first appears at position 3, so that is the answer even though 9 occurs again later. The same rule gives 3 for findloc(a, 9), while findloc(a, 5) returns 0 because 5 is not in the array. In the matrix the maximum is 8 at row 1, column 2; the matrix form of the result prints both subscripts. With dim=1 every column has its maximum in row 1, and with dim=2 the two rows have their maxima in columns 2 and 3.

$ gfortran i2.f90 -o i2
$ ./i2
 minloc:           6
 maxloc:           3
 findloc 9:           3
 findloc 5:           0
 maxloc of m:                 1           2
 maxloc dim 1:                1           1           1
 maxloc dim 2:                2           3

Counting and logical reduction

A comparison between an array and a scalar produces a logical array of the same shape. count returns how many elements of such a mask are true, while any and all answer whether at least one or every element is true. These three functions turn a question about the data into a single number or a single logical value, and they read almost like the sentence that states the question.

i3.f90
program i3
    implicit none
    integer :: a(6)

    a = [4, -2, 0, 7, -5, 9]
    print *, 'count positive:', count(a > 0)
    print *, 'count zero:    ', count(a == 0)
    print *, 'any negative:  ', any(a < 0)
    print *, 'all positive:  ', all(a > 0)
    print *, 'all nonzero:   ', all(a /= 0)
end program i3

Three values are positive, 4, 7 and 9, and one is zero. The array contains negative values, so any(a < 0) is true, but not all values are positive, so all(a > 0) is false. There is one zero, so all(a /= 0) is also false. A logical result is printed as T or F.

$ gfortran i3.f90 -o i3
$ ./i3
 count positive:           3
 count zero:               1
 any negative:   T
 all positive:   F
 all nonzero:    F

Masks

Most reduction functions accept a mask argument, a logical array of the same shape that selects the elements to include. The mask can be built from any condition, and it is evaluated before the reduction, so the array is not changed. A mask is the functional equivalent of an if inside a loop, written as an expression.

i4.f90
program i4
    implicit none
    integer :: a(6)

    a = [4, -2, 0, 7, -5, 9]
    print *, 'sum positive:', sum(a, mask=a > 0)
    print *, 'sum negative:', sum(a, mask=a < 0)
    print *, 'max positive:', maxval(a, mask=a > 0)
    print *, 'count > 3:   ', count(a > 3)
    print *, 'count even:  ', count(mod(a, 2) == 0)
end program i4

The positive values 4, 7 and 9 add to 20, and the negatives -2 and -5 add to -7; the zero belongs to neither mask. The largest positive value is 9. Three values exceed 3, and three are even, namely 4, -2 and 0. The last mask is itself an array expression, since mod works element by element, which shows that a mask is just another logical array.

$ gfortran i4.f90 -o i4
$ ./i4
 sum positive:          20
 sum negative:          -7
 max positive:           9
 count > 3:              3
 count even:             3

Pack, unpack and merge

pack collects the elements selected by a mask into a one-dimensional array, which is the natural way to extract a subset whose length is not known in advance. unpack does the reverse: it scatters a vector into the true positions of a mask and fills the rest with a given value. merge keeps the shape and chooses between two arrays element by element. pack shortens, unpack restores a shape, and merge never changes one.

i5.f90
program i5
    implicit none
    integer :: a(6)
    logical :: mask(6)

    a = [4, -2, 0, 7, -5, 9]
    mask = [.true., .false., .true., .false., .true., .false.]

    print *, 'pack:', pack(a, a > 0)
    print *, 'unpack:', unpack([1, 2, 3], mask, 0)
    print *, 'merge:', merge(a, 0, a > 0)
end program i5

Packing the positive values gives the vector 4, 7, 9. Unpacking the vector 1, 2, 3 into the alternating mask puts those numbers at positions 1, 3 and 5 and zero everywhere else, so the result has six elements again. merge returns 4, 0, 0, 7, 0, 9: the positive elements of a and zero in the places where the mask is false.

$ gfortran i5.f90 -o i5
$ ./i5
 pack:           4           7           9
 unpack:           1           0           2           0           3           0
 merge:           4           0           0           7           0           9

Reshape and spread

reshape gives an array a new shape, filling it in array element order, and spread adds a dimension by replicating an array along it. Spreading a vector of length three with dim=1 and ncopies=2 produces a 2 by 3 matrix whose two rows are the same; with dim=2 the result is a 3 by 2 matrix whose two columns are the same. The two functions are often used to prepare data for matmul or for output.

i6.f90
program i6
    implicit none
    integer :: v(6)
    integer :: m(2, 3)
    integer :: s(2, 3)
    integer :: row(3)

    v = [1, 2, 3, 4, 5, 6]
    row = [10, 20, 30]
    m = reshape(v, [2, 3])
    s = spread(row, 1, 2)

    print *, 'm:'
    print *, m
    print *, 'spread with dim 1:'
    print *, s
    print *, 'spread with dim 2:'
    print *, spread(row, 2, 2)
end program i6

The reshaped matrix holds the values 1 to 6 in column-major order, as in the previous article. The spread matrix printed in storage order is 10, 10, 20, 20, 30, 30, because each column of the 2 by 3 result contains one value repeated twice. Spreading along dimension 2 gives 10, 20, 30, 10, 20, 30, the same row repeated in both columns.

$ gfortran i6.f90 -o i6
$ ./i6
 m:
           1           2           3           4           5           6
 spread with dim 1:
          10          10          20          20          30          30
 spread with dim 2:
          10          20          30          10          20          30

The where construct

where applies an assignment to the elements of an array for which a mask is true and leaves the others alone. The one-line form handles a single statement, and the construct with elsewhere handles two or more branches. All masks are evaluated before any assignment happens, so the result does not depend on the order in which the elements are processed. It is the array equivalent of an if inside a loop.

i7.f90
program i7
    implicit none
    integer :: a(6)

    a = [-3, -1, 0, 2, 5, 7]
    where (a < 0)
        a = 0
    elsewhere (a > 0)
        a = a * 10
    end where
    print *, a
end program i7

The negative values become zero, the zero stays zero because no branch matches it, and the positive values are multiplied by ten. The result is 0, 0, 0, 20, 50 and 70. Writing the same transformation as a loop would need a temporary copy of the original array if the conditions had to see the old values, while where guarantees that behaviour by definition.

$ gfortran i7.f90 -o i7
$ ./i7
           0           0           0          20          50          70

A complete example

The program below summarises a list of exam scores. It computes the mean with sum and size, finds the best score and its position with maxval and maxloc, counts the passing scores with count, counts the scores above the mean, and extracts the good scores with pack. Every statistic is one expression over the whole array.

i8.f90
program i8
    implicit none
    integer :: scores(8)
    real :: mean

    scores = [72, 45, 88, 91, 60, 55, 78, 83]
    mean = real(sum(scores)) / size(scores)

    print *, 'mean:   ', mean
    print *, 'best:   ', maxval(scores), 'at', maxloc(scores)
    print *, 'worst:  ', minval(scores)
    print *, 'passed: ', count(scores >= 60)
    print *, 'above mean:', count(scores > mean)
    print *, 'good scores:', pack(scores, scores >= 80)
end program i8

The scores add to 572, so the mean is 71.5. The best score is 91 at position 4, and the worst is 45. Six scores are at least 60. Five scores lie above the mean, namely 88, 91, 78, 83 and 72, and pack collects the four scores of 80 or more as 88, 91, 83. The real division needs the real conversion, because sum(scores) / size(scores) would be an integer division and would give 71.

$ gfortran i8.f90 -o i8
$ ./i8
 mean:      71.5000000    
 best:             91 at           4
 worst:            45
 passed:            6
 above mean:           5
 good scores:          88          91          83

Next steps

The next article, Fortran allocatable arrays, gives arrays a size that is decided at run time, which is often needed before pack or findloc can be used on real data. The Fortran arrays article explains the constructors and sections used here, and the array arguments article shows how to pass these arrays to procedures. The intrinsic numeric functions article covers the scalar functions that where and the masks rely on.

Source

Fortran 2018 standard (J3/18-007r1)

GNU Fortran: SUM

GNU Fortran: MAXLOC

In this article we have reduced arrays with sum, product, minval and maxval, located values with maxloc, minloc and findloc, tested them with count, any and all, selected elements with masks, pack, unpack and merge, changed their shape with reshape and spread, and applied conditional assignments with where.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Fortran tutorials.