4

I am writing a C program where I operate nested for loops, one within another, as follows:

for(i[0] = 0; i[0] < n[0]; i[0]++)
  for(i[1] = 0; i[1] < n[1]; i[1]++)
    for(i[2] = 0; i[2] < n[2]; i[2]++)
      {
       do_lot_of_work(i, n, 3);
      }

As you can see, the above code has three nested for loops. In my program, it accounts for 3 dimensions. However, I want to make my program expandable, which can account of any number of dimensions, on the fly, as the user wishes; i.e. for 4 dimensions, I wish to have four nested for loops, and do the work as do_lot_of_work(i,n,4). Similarly, for any number of dimensions.

My question is: how to make the aforementioned nesting of for loops expandable?

Please note that, in order to achieve the goal, I am willing to sacrifice the inner for loops, but wish to keep the first for loop, in order to make my program parallel with OpenMP.

Nathan Tuggy
  • 2,237
  • 27
  • 30
  • 38
  • 2
    I don't suppose *recursion* is on your menu? – WhozCraig May 16 '15 at 01:45
  • It was, but I feared I might not use of the OpenMP if use recursive functions. But, anyway, it seems from the answers so far that I can still use the OpenMP at the innermost loop. Thanks, anyway, for pointing out! – Chandra Shekhar May 16 '15 at 10:32
  • Certainly. Recursion really is an elegant way to do this, and I see no reason you couldn't bracket that for-loop with OpenMP (been awhile, but I think it would work ok). Best of luck. – WhozCraig May 16 '15 at 10:35

2 Answers2

4

When the nesting level is not known at compile time, use recursion to achieve the same effect:

void do_work(int i[], int n[], int pos, int size) {
    if (pos == size) {
        // All i-s are set - we are ready to roll
        do_lot_of_work(i, n, size);
    } else {
        for (i[pos] = 0 ; i[pos] < n[pos] ; i[pos]++) {
            do_work(i, n, pos+1, size);
        }
    }
}
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
4

Use a recursive function.

void tons_of_work( int i[], int n[], int dims ) {
    loop_level( 0, i, n, dims );
}

void loop_level( int level, int i[], int n[], int dims ) {
    if ( level == dims ) {
        do_lot_of_work( i, n, dims );
    } else {
        int * ilevel = & i[ level ];
        for ( *ilevel = 0; *ilevel != n[ level ]; ++ *ilevel ) {
            loop_level( level + 1, i, n, dims );
        }
    }
}

loop_level calls itself to produce nested loops, until the innermost loop level is reached. Then it starts to do "real" work instead.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421