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

Interpretation of nested WHERE

Andreas_Z_
New Contributor I
314 Views

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

0 Kudos
1 Solution
Ron_Green
Moderator
144 Views

Good news - yes, bug is still there in the last release.  It's fixed in the upcoming 2023.0 packages.  Also fixed in the IFX compiler coming out in the 2023.0 packages, version 2023.0.0 for IFX.  These should be coming out very soon.  Hopefully before the end of the month.

 

Before and current 2021.7 compiler

 

 

$ ifort -g -traceback -O0 -fpe0 -fp-model source wheredat.f90 -V
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.7.1 Build 20221019_000000
Copyright (C) 1985-2022 Intel Corporation.  All rights reserved.

 Intel(R) Fortran 2021.7.1-1776
GNU ld version 2.37-27.fc36
rwgreen@orcsle153:~/quad/qnew$ ./a.out
forrtl: error (73): floating divide by zero
Image              PC                Routine            Line        Source             
libc.so.6          00007FCA04537A70  Unknown               Unknown  Unknown
a.out              000000000045C5A9  Unknown               Unknown  Unknown
a.out              00000000004042FF  MAIN__                     14  wheredat.f90
a.out              000000000040419D  Unknown               Unknown  Unknown
libc.so.6          00007FCA04522590  Unknown               Unknown  Unknown
libc.so.6          00007FCA04522649  __libc_start_main     Unknown  Unknown
a.out              00000000004040B5  Unknown               Unknown  Unknown
Aborted (core dumped)
r

 

 

and with an early build of the 2021.8 compiler coming in oneAPI 2023.0 packages very soon.  Note that the build date will probably be different in the product compiler.  version will be 2021.8.0 like this one.

 

 

 ifort -g -traceback -O0 -fpe0 -fp-model source wheredat.f90 -V
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.8.0 Build 20221107_000000
Copyright (C) 1985-2022 Intel Corporation.  All rights reserved.

 Intel(R) Fortran 2021.8.0-1196
GNU ld version 2.37-27.fc36
rwgreen@orcsle153:~/quad/qnew$ ./a.out
  arrayC,       arrayD 
  1.0000E+00    1.0000E+00
  1.0000E-02    1.0000E-02
  1.1111E+00    1.1111E+00
  1.0000E-10    1.0000E-10
 
 ... done.

 

 

View solution in original post

3 Replies
Kevin_D_Intel
Employee
314 Views

Thank you for the very convenient reproducer. In reviewing WHERE in the Fortran 2008 Standard, I believe this is a defect. It seems the compiler is not applying the outer WHERE mask during evaluation/execution of the inner WHERE as it should. I reported this to Development for their analysis and will let you know what I hear back.

(Internal tracking id: DPD200376235)

Andreas_Z_
New Contributor I
157 Views

Hi,
I've noticed that the above stated issues with nested WHERE blocks still exists in the ifort version 2021.7.0.

Is there an update on a fix in a future edition of the compiler?

Ron_Green
Moderator
145 Views

Good news - yes, bug is still there in the last release.  It's fixed in the upcoming 2023.0 packages.  Also fixed in the IFX compiler coming out in the 2023.0 packages, version 2023.0.0 for IFX.  These should be coming out very soon.  Hopefully before the end of the month.

 

Before and current 2021.7 compiler

 

 

$ ifort -g -traceback -O0 -fpe0 -fp-model source wheredat.f90 -V
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.7.1 Build 20221019_000000
Copyright (C) 1985-2022 Intel Corporation.  All rights reserved.

 Intel(R) Fortran 2021.7.1-1776
GNU ld version 2.37-27.fc36
rwgreen@orcsle153:~/quad/qnew$ ./a.out
forrtl: error (73): floating divide by zero
Image              PC                Routine            Line        Source             
libc.so.6          00007FCA04537A70  Unknown               Unknown  Unknown
a.out              000000000045C5A9  Unknown               Unknown  Unknown
a.out              00000000004042FF  MAIN__                     14  wheredat.f90
a.out              000000000040419D  Unknown               Unknown  Unknown
libc.so.6          00007FCA04522590  Unknown               Unknown  Unknown
libc.so.6          00007FCA04522649  __libc_start_main     Unknown  Unknown
a.out              00000000004040B5  Unknown               Unknown  Unknown
Aborted (core dumped)
r

 

 

and with an early build of the 2021.8 compiler coming in oneAPI 2023.0 packages very soon.  Note that the build date will probably be different in the product compiler.  version will be 2021.8.0 like this one.

 

 

 ifort -g -traceback -O0 -fpe0 -fp-model source wheredat.f90 -V
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.8.0 Build 20221107_000000
Copyright (C) 1985-2022 Intel Corporation.  All rights reserved.

 Intel(R) Fortran 2021.8.0-1196
GNU ld version 2.37-27.fc36
rwgreen@orcsle153:~/quad/qnew$ ./a.out
  arrayC,       arrayD 
  1.0000E+00    1.0000E+00
  1.0000E-02    1.0000E-02
  1.1111E+00    1.1111E+00
  1.0000E-10    1.0000E-10
 
 ... done.

 

 

Reply