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 /)
0

2 Answers 2

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
Sign up to request clarification or add additional context in comments.

2 Comments

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.
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....)
8

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.