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

different "IF" lazy evalation in Windows and Linux

Orlando_R_
Beginner
370 Views

Hello  

Theres is a legacy code  we  have to compile in Linux and Windows. 

in Linux we have  ifort 15 and in Windows  ifort 11,  and the project is rather  big, so code modification will be the last option

our Problem  is in the following IF, for example:

INTEGER VECTOR(10)
DO I=1,10
    IF ( I .LT.10 .AND.  VECTOR(I+1) .GT. 0) THEN
!        do something
    END IF
ENDDO

The classic  IF Lazy Evaluation : If the first condition is false, in Linux , the rest  will be not evaluated , therefore, VECTOR(11) will be not evaluated. In Windows, however,  the same code produces the expected out of bound error:  forrtl: severe Subcript #1 of Array VECTOR has value 11

I am not aware of the details , I think we had another Compiler in Windows, which didn't have this behavior, and the  code was developed that way.

Of course this works everywhere

INTEGER VECTOR(10)
DO I=1,10
    IF ( I .LT.10 ) THEN 
        IF (VECTOR(I+1) .GT. 0) THEN
!          do something
        ENDIF
    END IF
ENDDO

Unfortunately, our  IF's are a bit more complex than that, and we have to  much code  to edit . Is there a  flag we can use in compile time to force the same behavior in Windows as in Linux?

Thanks 

0 Kudos
4 Replies
Orlando_R_
Beginner
370 Views

I found this , so i think we  have to modify our code

https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/275470

sorry for double posting !

0 Kudos
TimP
Honored Contributor III
370 Views

Yes, you found the discussion from the expert. 

There is no valid Windows vs. linux tradition on such matters; in fact, the f2c script, which does follow your expectation on short-cutting compound IF, is much easier to find on old linux installations than on Windows.

By the way, although some might expect a competent optimizing compiler to take care of it, in this case it seems you should have written

DO I=1,9

3     IF (  VECTOR(I+1) .GT. 0) THEN
4 !        do something
5     END IF
6

ENDDO

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
370 Views

In the cases where you have a relatively long complex IF expression that you want "lazy left-to-right" evaluation .AND. you do not want to add the additional THEN-ENDIF scoping statements, then you can insert a LOGICAL function that has the THEN-ENDIF qualifiers.

Alternatively

LOGICAL :: doIF
...
doIF = (I .LT. 10)
if(doIF) doIF = (VECTOR(I) .GT. 0)
if(doIF) THEN
 ! do something
endif ! Note only one endif

Jim Dempsey
 

0 Kudos
mecej4
Honored Contributor III
370 Views

The simple way of correcting the code in #1 is to change the upper limit of the DO index to 9 (instead of 10). Doing so will simultaneously work in the same way as the evaluation of the equivalent code in C (with left-to-right, short-circuit evaluation) and also avoid an out of bounds access of VECTOR(11).

If you have other DO statements with IF statements in the loop where ELSE and ELSE IF(..) THEN clauses are present, fixing the code will be a bit more complicated. You could add statements in the loop such as IF(I.GT.9)CYCLE preceding statements that test VECTOR(I+1), etc.

Note that there is more urgency behind fixing the code than merely avoiding out-of-bounds subscript errors. If you compile without /CHECK:bounds, the code may make invalid memory accesses or the program can give incorrect results because incorrect branches are taken because invalid memory reads were used in selecting the branches.

0 Kudos
Reply