Quantcast
Channel: Intel® Fortran Compiler
Viewing all articles
Browse latest Browse all 3270

Interpretation of nested WHERE

$
0
0

Hi,

I am trying to understand if my interpretation of nested WHERE blocks is incorrect or if the compiler is producing an incorrect execution.

I encountered numerical floating point exceptions in a large program because of the execution of LOG10(0.D00) inside a nested WHERE block, even though execution of array arguments with values <= 0.0D0 should be prevented by a mask in the outer WHERE block.

The following test code reproduces the problem when the compiler flag /fpe:0 is set for floating point exception handling.

!** A simple program to test issues with nested WHERE constructs **
PROGRAM NestedWHERE

IMPLICIT NONE

INTEGER(4) :: j
INTEGER(4), PARAMETER :: n = 4, k = 100
REAL(8),DIMENSION(n) :: arrayA, arrayB, arrayC, arrayD
!-------------------------------------------------------

arrayA = [1.0D0, 2.0D0, 0.0D0, 4.0D4]
arrayB = [1.0D0, 2.0D-2, 0.0D0, 4.0D-6]

!Nested WHERE block
WHERE (arrayA(1:n) > 0.0D0)
    WHERE (ABS(LOG10(arrayA(1:n))) + ABS(LOG10(arrayB(1:n))) < 300.0D0) !issue: LOG10 seems to be executed for all array elements (including elements where arrayA == 0.0D0). Why is the mask (of the outer WHERE) not applied?
        arrayC(1:n) = arrayB(1:n)/arrayA(1:n)
    ELSEWHERE
        arrayC(1:n) = 8.0D-4
    ENDWHERE
ELSEWHERE
    arrayC(1:n) = 1.111111111
ENDWHERE

!The procedure of the above nested WHERE block expressed by DO-loop and nested IF-END IF blocks (works as expected).
DO j = 1,n
    IF (arrayA(j) > 0.0D0) THEN
        IF (ABS(LOG10(arrayA(j))) + ABS(LOG10(arrayB(j))) < 300.0D0) THEN
            arrayD(j) = arrayB(j)/arrayA(j)
        ELSE
            arrayD(j) = 8.0D-4
        ENDIF
    ELSE
        arrayD(j) = 1.111111111
    ENDIF
ENDDO !J

WRITE(*,'(A23)') "  arrayC,       arrayD "
DO j = 1,n
    WRITE(*,'(2(ES12.4,2x))') arrayC(j), arrayD(j)
ENDDO
WRITE(*,*) ""
WRITE(*,*) "... done."
READ(*,*)

END PROGRAM

I use the Intel(R) Visual Fortran Compiler 16.0.0.110 [IA-32], in MS Visual Studio 2010 on Windows 7.

The ifort command line used is: 
/nologo /debug:full /Od /warn:interfaces /fpe:0 /fp:source /module:"Debug\\" /object:"Debug\\" /Fd"Debug\vc100.pdb" /traceback /check:bounds /check:stack /libs:static /threads /dbglibs /c

The following is an excerpt of the call stack at the point of floating point exception:
     TestNestedWHERE.exe!___libm_log10_w7()  + 0x226 bytes    
    TestNestedWHERE.exe!NESTEDWHERE()  Line 15 + 0x45 bytes    Fortran

I am not sure if my use of nested WHERE statements in this case is incorrect (even though both ABS and LOG10 are elemental intrinsic functions) or if it is supposed to work according to the Fortran standard.

 

Andi


Viewing all articles
Browse latest Browse all 3270

Latest Images

Trending Articles



Latest Images

<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>