drjrm3
drjrm3

Reputation: 4728

n nested for loops in fortran90

i have read some topics on this, but i don't quite think it answers my question. if it does then please direct me to the correct topic and i will definitely look again.

here is my problem:

i want to write a for loop which will cycle through every possible combination of an array where the array is of length 'n'.

that is, if n = 2 then my for loop would be

do i1 = 1,2
    do i2 = 1,2
         ! do stuff here
    enddo
enddo

while if n = 3 then my array would look like

do i1 = 1,3
    do i2 = 1,3
         do i3 = 1,3
             ! do stuff here
         enddo
    enddo
enddo

and so on. how would i go about writing a routine which would do this automatically by simply an an input variable 'n'?

Upvotes: 1

Views: 1291

Answers (2)

andrew cooke
andrew cooke

Reputation: 46892

if you write out the indices, what you have is an n-digit number in base n (almost - there's an offset of 1 because you are using 1-based indices in fortran). and what you are asking for is every possible value that number can take.

in other words, if we use 0-based indices for a moment for simplicity, you have:

  • n=2, values=00,01,10,11 (binary counting from 0 to 3)
  • n=3, values=000,001,002,010,011,012,020,021,022, 100,101,102,110,111,112,120,121,122, 200,201,202,210,211,212,220,221,222 (ternary(?) counting from 0 to 26)

so what you are asking is how to do this in the general case.

and you can do that by using an array to hold the n digits, starting at [0,0....0]. then, within a "while" loop (which will replace your n nested for loops), try to increment the right-most entry (digit). if that is equal to n, then go back to zero and increment to the left. once you manage to increment a value without reaching n then you are "done" and can use the numbers as your indices.

it's pretty simple - you're just adding 1 each time.

then, for fortran's 1-based indexing, add 1 to each digit. in other words, change the above to start with 1s and move left at n+1.

for example, for n=4:

  • start with [1,1,1,1]
    • do your inner loop action
  • increment rightmost to [1,1,1,2]
    • do your inner loop action
  • increment rightmost to [1,1,1,3]
    • do your inner loop action
  • increment rightmost to [1,1,1,4]
    • do your inner loop action
  • increment rightmost to [1,1,1,5]
  • the digit you incremented is now at n+1, which means back to 1 and increment digit to left [1,1,2,1]
    • do your inner loop action
  • increment rightmost to [1,1,2,2]
    • do your inner loop action
  • etc..

Upvotes: 1

haraldkl
haraldkl

Reputation: 3819

I guess you could only do this by collapsing the loops into a single n**n loop, and compute the individual n indices out of the collapsed global index (or simply counting them up with different strides).

Edit: An attempt to put this into sample code:

do i=1,n**n
  do j=1,n
    ind(j) = mod((i-1)/max((j-1)*n,1),n) + 1
  end do
  ! Some code using ind(1:n)
end do

Upvotes: 1

Related Questions