Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28996 Discussions

A do-variable within a DO body shall not appear in a variable definition context. [I]

emreka82
Beginner
3,267 Views

I have a code in which I wolud like to define i as the end value, let me make it clear by writing here:

 [fortran]

integer function cornerio

real    :: term1, term2, term3, term4

do i=1,nelem

!......

if(abs(term1)<=1e-20) then
term1=0.
end if
if(abs(term2)<=1e-20) then
term2=0.
end if
if(abs(term3)<=1e-20) then
term3=0.
end if
if(abs(term4)<=1e-20) then
term4=0.
end if


if( term1==0 .and. term2==0 .and. term3==0 .and. term4==0 ) then
cornerio=-1
i=nelem 
else
if(term1/=0) then
if((term1*term2)>=0 .and. (term1*term3)>=0 .and. (term1*term4)>=0) then
cornerio=-1
i=nelem
end if

else if(term2/=0) then
if((term2*term1)>=0 .and. (term2*term3)>=0 .and. (term2*term4)>=0) then
cornerio=-1
i=nelem
end if

else if(term3/=0) then
if((term3*term1)>=0 .and. (term3*term2)>=0 .and. (term3*term4)>=0) then
cornerio=-1
i=nelem
end if

else if(term4/=0) then
if((term4*term1)>=0 .and. (term4*term2)>=0 .and. (term4*term3)>=0) then
cornerio=-1
i=nelem
end if

else 
print*, "ERROR"
end if

end if 
end do

return

end function cornerio

[/fortran]

When I compile this simple code, I got the error "A do-variable within a DO body shall not appear in a variable definition context.   " for the lines including "i=nelem". How can I solve this problem, without changing the logic ( İ=nelem inside the if-else statements). Thanks..

Emre

0 Kudos
14 Replies
A__Valle
Beginner
3,267 Views
Dear Emre, You cannot change the counting variable using an assignment within a DO-loop. What you are trying to do in my opinion is leaving the DO-loop by setting the counter to the max. The correct way to exit a DO loop is the EXIT statement. If this is not what you want, you might have a look at DO WHILE Dirk
0 Kudos
Les_Neilson
Valued Contributor II
3,267 Views
Emre In the code you supplied you replace the i=nelem statement with either return or exit RETURN will return from the function but if you have any code you want executed after the end of the do-loop then EXIT will end the do-loop If you have nested do-loops then you can name each loop and exit "loop-name" will end that particular loop. See the help for EXIT Statement. Les
0 Kudos
emreka82
Beginner
3,267 Views
D.W. van Meeuwen wrote:

Dear Emre,

You cannot change the counting variable using an assignment within a DO-loop. What you are trying to do in my opinion is leaving the DO-loop by setting the counter to the max. The correct way to exit a DO loop is the EXIT statement.
If this is not what you want, you might have a look at DO WHILE

Dirk

Thanks for a quick answer Dirk, the interesting thing is when I wrote exactly the same code in C++, I did not encounter any problem. I will try EXIT statement ( is it solely EXIT, or do I need any information (such as "go to" statement)), I think that do-while is more reliable solution. Thanks again for these ideas Dirk.
0 Kudos
emreka82
Beginner
3,267 Views
That is the solution: [fortran] integer function cornerio real :: term1, term2, term3, term4 i=1 do while (i==nelem) !...... if(abs(term1)<=1e-20) then term1=0. end if if(abs(term2)<=1e-20) then term2=0. end if if(abs(term3)<=1e-20) then term3=0. end if if(abs(term4)<=1e-20) then term4=0. end if if( term1==0 .and. term2==0 .and. term3==0 .and. term4==0 ) then cornerio=-1 i=nelem else if(term1/=0) then if((term1*term2)>=0 .and. (term1*term3)>=0 .and. (term1*term4)>=0) then cornerio=-1 i=nelem end if else if(term2/=0) then if((term2*term1)>=0 .and. (term2*term3)>=0 .and. (term2*term4)>=0) then cornerio=-1 i=nelem end if else if(term3/=0) then if((term3*term1)>=0 .and. (term3*term2)>=0 .and. (term3*term4)>=0) then cornerio=-1 i=nelem end if else if(term4/=0) then if((term4*term1)>=0 .and. (term4*term2)>=0 .and. (term4*term3)>=0) then cornerio=-1 i=nelem end if else print*, "ERROR" end if end if i=i+1 end do return end function cornerio [/fortran]
0 Kudos
Les_Neilson
Valued Contributor II
3,267 Views
If you have reached a required condition within the do-loop then exit is what you need. In this instance (and generally speaking most of the time) you do not need a "go to". Les
0 Kudos
emreka82
Beginner
3,267 Views
Les Neilson wrote:

Emre
In the code you supplied you replace the i=nelem statement with either
return
or
exit

RETURN will return from the function
but if you have any code you want executed after the end of the do-loop then
EXIT will end the do-loop

If you have nested do-loops then you can name each loop and exit "loop-name" will end that particular loop.
See the help for EXIT Statement.

Les

Also, thank you Les. There are a few solutions, I choose do-while as you can see above, it is correct right ?
0 Kudos
Les_Neilson
Valued Contributor II
3,267 Views
1. In the code you have shown nelem is not declared nor assigned a value. 2. The do while will execute once ONLY if nelem has the value 1 (At the end of the if statements i is increased by 1 and no longer equals nelem) 3. If nelem has a value other than 1 the loop will not execute at all. Les
0 Kudos
Steven_L_Intel1
Employee
3,267 Views
emreka82 wrote:

the interesting thing is when I wrote exactly the same code in C++, I did not encounter any problem.

That's because C++ is not Fortran. While a C++ "for" loop might look similar to a Fortran DO loop, and in many cases they are interchangeable, the semantics are really quite different. A C/C++ for loop is much more like the Fortran DO WHILE - you specify start and end conditions and an expression that changes the loop variable each iteration. The end condition is an expression that is evaluated each time through the loop, and the increment variable is just that, a variable. In a regular Fortran DO loop, it is in effect a counted loop where the count is determined before the loop ever starts execution, according to a formula specified in the standard. Once the loop begins execution, the count cannot be changed (at least not if you're following the standard.) In older compilers, you could sometimes change the loop control variable and have the effect you wanted, but most modern optimizing compilers don't let you do this. The suggestions to use EXIT (also look up CYCLE) are the right way to go if you want to prematurely exit a loop (or skip iterations.)
0 Kudos
jimdempseyatthecove
Honored Contributor III
3,267 Views
>>do while (i==nelem) do while(i .LE. nelem) using exit or return is much clearer. In C/C++ wouldn't you use "break;"? Jim Dempsey
0 Kudos
emreka82
Beginner
3,267 Views
I read all the comments, yeah do-while does not provide the same outputs, exit can be more reliable option.
Steve Lionel (Intel) wrote:

Quote:

emreka82 wrote:

the interesting thing is when I wrote exactly the same code in C++, I did not encounter any problem.

That's because C++ is not Fortran. While a C++ "for" loop might look similar to a Fortran DO loop, and in many cases they are interchangeable, the semantics are really quite different.

A C/C++ for loop is much more like the Fortran DO WHILE - you specify start and end conditions and an expression that changes the loop variable each iteration. The end condition is an expression that is evaluated each time through the loop, and the increment variable is just that, a variable.

In a regular Fortran DO loop, it is in effect a counted loop where the count is determined before the loop ever starts execution, according to a formula specified in the standard. Once the loop begins execution, the count cannot be changed (at least not if you're following the standard.) In older compilers, you could sometimes change the loop control variable and have the effect you wanted, but most modern optimizing compilers don't let you do this.

The suggestions to use EXIT (also look up CYCLE) are the right way to go if you want to prematurely exit a loop (or skip iterations.)

Steve, But a regular do while loop of C++ should have the same effect of do while-loop of fortran, right ? I mean both the figurative and the output of them. Such as; C++: [cpp] int i=0; do { i++; cout<<"i:"<<
0 Kudos
emreka82
Beginner
3,267 Views
Sorry for the c++ code above, I cannot write it inside the cpp code brackets.
0 Kudos
emreka82
Beginner
3,267 Views
Another thing came to my mind: Is there a difference between exit(EXIT_FAILURE); of C++ and exit of Fortran ? If so, then what should I use to have the same effect of exit(EXIT_FAILURE); in Fortran ?
0 Kudos
IanH
Honored Contributor III
3,267 Views
emreka82 wrote:
... But a regular do while loop of C++ should have the same effect of do while-loop of fortran, right ? I mean both the figurative and the output of them. Such as;
C++:
[cpp] int i=0; do { i++; cout<<"i:"< cout< cout< } while((max*bodydiv)<=(domsize/pow(2.,unidiv+i))); [/cpp] [fortran] i=1 do while((max*bodydiv)<=(domsize/(2.**(unidiv+i)))) i=i+1 print*, "i:", i print*, max*bodydiv print*, domsize/(2**(unidiv+i)) end do [/fortran]
In C in a do statement, the evaluation of the controlling expression (the loop continuation test) takes place after each execution of the loop body (the loop body of the statement is always executed at least once). In Fortran in the DO WHILE form, the expression in the WHILE is tested before any statements in the body of the construct is executed (the loop body may not be executed). You might find some differences in the initial value of i between your two examples too.
0 Kudos
Mark_Lewy
Valued Contributor I
3,267 Views
emreka82 wrote:

Another thing came to my mind: Is there a difference between exit(EXIT_FAILURE); of C++ and exit of Fortran ? If so, then what should I use to have the same effect of exit(EXIT_FAILURE); in Fortran ?

Yes, they are different. The Fortran exit statement is equivalent to C/C++ break statement. The nearest equivalent to C/C++ exit() is the Fortran stop statement; 'stop 1' is equivalent to exit(EXIT_FAILURE).
0 Kudos
Reply