Assigning values of an array in a loop

108 views Asked by At

In my code:

DO i=1,numJog,1
    IF(val(i) .EQV. .TRUE.)THEN
            DO j=1,contVenc,1
                result(j) = i
            END DO
    END IF
END DO

Where val is a logical array, and result is a integer array.

For example, if val is:

F
T
F
T

Then, i=2 and i=4.

But the result array just write 4 twice. For example:

DO i=1,contVenc,1
    WRITE(*,*) result(i)
END DO

The result is:

4
4

Instead of

2
4

If I make some changes in my code like:

DO i=1,numJog,1
    IF(val(i) .EQV. .TRUE.)THEN
        WRITE(*,*) i
    END IF
END DO

The result is:

2
4

As I wanted.

Conclusion, I think this second loop is causing this problem.

1

There are 1 answers

0
francescalus On BEST ANSWER

Yes, your second loop is at fault here. You haven't said what contVenc is, but it crucially doesn't change at any point in the fragment you have there. That just means that the same elements of result are being assigned to whenever you have a .TRUE. in val.

In your case they are both set to 2 for the first .TRUE. and are then both set to 4 for the second.

You are more likely to mean something like (with extra tidying):

j = 0
DO i=1,numJog
    IF (val(i)) THEN
        j = j+1   ! Test this as a bound
        result(j) = i
    END IF
END DO

But then, I'd just use PACK. Your intended loop has the same effect as

result(1:COUNT(val(1:numJog))) = PACK([(i,i=1,numJog)], val(1:numJog))

Again hoping that result is large enough.

That said, if numJog is just the size of the array val (that is, you aren't just doing this on a sub-array) then, as High Performance Mark comments,

result(1:COUNT(val)) = PACK([(i,i=1,SIZE(val))], val)

avoids tracking this size separately.

Finally, with result an allocatable (Fortran 2003) array you needn't even (but still can) worry about counting the number of wanted indices and that the array is sufficiently large:

result = PACK([(i,i=1,SIZE(val))], val)