13

I want to initialize an array on one line with an implicit do loop. However, I always get a syntax or shape error. Can anyone help me correct the following construct?

integer myarray :: (maxdim, nr)

myarray(1:maxdim,nr) = (/ (/i,i=1,maxdim/),nr /)
nbro
  • 15,395
  • 32
  • 113
  • 196
tarrasch
  • 2,630
  • 8
  • 37
  • 61

2 Answers2

22

You are initializing an array with MAXDIM rows and NR columns, and it looks like each column contains the integers 1 to MAXDIM.

As a first step, go ahead and write out the actual DO-loop:

do j=1,NR
    do i=1,MAXDIM
        myarray(i,j) = i
    end do
end do

Collapse the inner loop to an implicit loop structure:

do j = 1,NR
    myarray(1:MAXDIM,j) = (/ (i, i=1,MAXDIM) /)
end do

When we try to collapse the outer loop, though, something strange happens:

myarray = (/ ((/ (i, i=1,MAXDIM) /), j=1,NR) /)

Now, I get an incompatible ranks error as you did. Since I'm not very good at the implicit do-loops either, I looked at the shape intrinsic results for the array constructor:

print *, shape(myarray)
print *, shape((/ ((/ (i, i=1,MAXDIM) /), j=1,NR) /))

This prints out

   5      10
  50

The array constructor is simply expanding a 1-D array , flattening any nested array constructions. We can actually drop the second set of (/ /) to simplify. Since everything is already in the proper order, we can use the reshape intrinsic to ensure proper rank. My full test program is then:

program sotest
    implicit none

    integer, parameter :: MAXDIM = 5
    integer, parameter :: NR     = 10

    integer :: i
    integer :: j
    integer :: myarray(MAXDIM, NR)
    integer :: myarray_implicit(MAXDIM, NR)

    do j = 1,NR
        do i = 1,MAXDIM
            myarray(i,j) = i
        end do
    end do 

    myarray_implicit = reshape((/ ((i,i=1,MAXDIM), j=1,NR) /), (/ MAXDIM, NR /))

    print *, all(myarray == myarray_implicit)
 end program sotest
Tim Whitcomb
  • 10,447
  • 3
  • 35
  • 47
  • 8
    Note that it is also valid to write `myarray_implicit = reshape((/ ((i,i=1,MAXDIM), j=1,NR) /), shape(myarray_implicit))` to avoid explicitly typing out the dimensions of your matrix again. – Markus Jun 09 '13 at 20:25
  • It's odd that one can't initialize a 2D array implicitly. I feel like this ought to be a bug in Fortran rather than a feature. (With a decade of Fortran experience, I'm getting used to that....) – jvriesem May 15 '18 at 20:02
7

The implicit do loop will only create a vector so you'll have to reshape that. Something like this:

integer, dimension(m,n) :: myarray
integer :: ix, jx
...
myarray = reshape( [ (ix, ix = 1, m*n) ], [ m, n ] )

or perhaps you want a more complicated, nested, implied-do loop:

myarray = reshape( [ ((ix+jx, ix = 1, m), jx = 1, n) ], [ m, n ] )

Note that I'm using the Fortran2003 convention of [ ] to delimit array constructions, rather than (/ /). Note also that you have to declare the implied do loop index variables.

High Performance Mark
  • 77,191
  • 7
  • 105
  • 161