Intel Fortran compiler bug report (this is not bug in ROMS)

Discussion on computers, ROMS installation and compiling

Moderators: arango, robertson

Post Reply
Message
Author
User avatar
shchepet
Posts: 188
Joined: Fri Nov 14, 2003 4:57 pm

Intel Fortran compiler bug report (this is not bug in ROMS)

#1 Unread post by shchepet »

I encountered the following behavior:

internal Fortran reading operation fails to return non-zero status if
one attempts to read a real*8 from a string which is does not contain
a valid number, and therefore the reading operation must fail.

This may have some implication for ROMS, ever more for plotting package
(since it uses string-to-number conversions) and other codes. Please take
a look at this test program and see whether you have similar experiences.

Code: Select all

      program reading_error
      implicit none
      real(kind=8) value
      character(len=16) string
      integer ierr

      string='1.6'
      read(string,*,iostat=ierr) value
      write(*,*) string, value, ierr

      string='-3.1415926D-3'
      read(string,*,iostat=ierr) value
      write(*,*) string, value, ierr

      string='123456789012346'
      read(string,*,iostat=ierr) value
      write(*,*) string, value, ierr

      string='1.D+02'
      read(string,*,iostat=ierr) value
      write(*,*) string, value, ierr

      string='4D+03'        !<-- "semi-legal" (no decimal point),
      read(string,*,iostat=ierr) value   ! but actually read OK
      write(*,*) string, value, ierr

      string='2E4'          !<-- "semi-legal", but actually read OK
      read(string,*,iostat=ierr) value
      write(*,*) string, value, ierr

!??
!?? The following two cases should cause reading error, because
!?? the content of the string is not a number, so as the outcome
!?? ierr should be different from 0, while the number should not
!?? be read (hence variable "value" retains its previous value;
!?? this program compliled using GNU gfortran compiler, the
!?? outcome is, indeed a non-zero ierr, and "value" retains its
!?? value from above.
!??
!?? If complied using Intel "ifort" (versions/package IDs tested:
!?? l_fc_c_9.1.040, l_fc_p_10.1.011, and l_cprof_p_11.0.081) the
!?? outcome is value becomes -1.0000, and ierr becomes 0.
!??
!?? This behavior occurs both if using 64- (x86_64) and 32-bit
!?? (i686) compiler and operating system
!??

      string='test.nc'        !<-- SHOULD CAUSE iostat ERROR
      read(string,*,iostat=ierr) value
      write(*,*) string, value, ierr

      string='test_0000.nn'   !<-- SHOULD CAUSE iostat ERROR
      read(string,*,iostat=ierr) value
      write(*,*) string, value, ierr

      stop
      end


User avatar
arango
Site Admin
Posts: 1367
Joined: Wed Feb 26, 2003 4:41 pm
Location: DMCS, Rutgers University
Contact:

Re: Intel Fortran compiler bug report (this is not bug in ROMS)

#2 Unread post by arango »

Yes, I got the same behavior:

Code: Select all

 1.6                1.60000000000000                0
 -3.1415926D-3    -3.141592600000000E-003           0
 123456789012346    123456789012346.                0
 1.D+02             100.000000000000                0
 4D+03              4000.00000000000                0
 2E4                20000.0000000000                0
 test.nc           -1.00000000000000                0
 test_0000.nn      -1.00000000000000                0
This is a internal data transformation that I regularly use to extract logical, integers, and floating-point numbers from a string variable. The binary characters in the string are always numbers with or without legal formated letters. However, I never use it to read non-numerical values (strings) into variables that are not strings (value variable above).

By the way, I get the same behavior with the pgf90 compiler. However, the gfortran compiler gives:

Code: Select all

 1.6                1.60000000000000                0
 -3.1415926D-3    -3.141592600000000E-003           0
 123456789012346    123456789012346.                0
 1.D+02             100.000000000000                0
 4D+03              4000.00000000000                0
 2E4                20000.0000000000                0
 test.nc            20000.0000000000               11
 test_0000.nn       20000.0000000000               11
It gives a nonzero IOSTAT.

User avatar
shchepet
Posts: 188
Joined: Fri Nov 14, 2003 4:57 pm

Re: Intel Fortran compiler bug report (this is not bug in ROMS)

#3 Unread post by shchepet »

OK, I is kind of serious, since it affects several of our codes.
I investigated it a little bit further, and I found that:

1. the failure to return non-zero error status depends on the
initial symbol of the string. To see it, compile and execute
the following code:

Code: Select all

      program reading_error
      implicit none
      real(kind=8) value
      character(len=16) string
      integer i, ierr
      do i=21,127
        string=char(i)/ /'xyz'

        read(string,*,iostat=ierr) value
        write(*,*) i,' ', string, value, ierr
      enddo
      stop
      end
then you will see that most of the time it works correctly
(iostat returns non-zero error status), but there are symbols
which make iostat return zero, which is wrong. There are 7 such
symbols:


, / F T f t


2. This is not just internal-read error, but is read error in
general. You can observe exactly the same behavior when reading
from a file, or from standard input (from the screen or via
redirection -- does not matter). For example, in input file
"roms.in" for my code I may specify

dt = txyz

and instead of complaining about reading error and quitting
immediately, the code ends up having dt = -1.00000 and proceeds
without any error message despite the fact that I ALWAYS check
iostat returned value in my read_inputs.F. Obviously the code
computationally blows up sometime later. If I specify

dt = xyz

now the first letter is "x" and not the one among the 7 above,
then the code quits instantly complaining about the error, as it
should.

I tested Rutgers code, and it also fails to quit immediately,
despite the obvious error.

Since virtually all input in modern-day roms codes and associated
protting packages and pre- post processing tools is implemented as
a two-stage procedure: read input as character string, then convert
it into numbers, the following "work-around" is to avoid the use of
internal Fortran read altogether, and to replace it with function
call, i.e.,

Code: Select all

        read(string,*,iostat=ierr) value

is replaced with

Code: Select all

         ierr=string_to_dble(string, value)
where "string_to_dble" is the following custom-made function

Code: Select all

      function string_to_dble(string, value)
!
! The purpose of this function is to read a double precision
! value from a string, basically an equivalent of
!
!         read(string,*,iostat=ierr) value
!
! while avoiding the use of FORTRAN internal read. This is needed
! just a workaroud because of Intel compiler issue # 548345, which
! is a failure to return a non-zero error status for certain
! strings, if the operation fails.
!
      implicit none
      integer string_to_dble
      character(len=*) string
      real*8 value
      integer is,ie, i, isgn, msgn, ierr, k, m,n,dcm_pt, exp_pt

      ie=len(string)
      do while (ie.gt.1 .and. string(ie:ie).eq.' ')
        ie=ie-1
      enddo
      if (string(ie:ie).eq.' ') ie=ie-1

      is=1
      isgn=1
      if (string(1:1).eq.'+') then
        is=2
      elseif(string(1:1).eq.'-') then
        is=2
        isgn=-1
      endif

      ierr=0
      msgn=1
      exp_pt=0
      dcm_pt=0
      k=0
      m=0
      n=1
      i=is-1
      do while(i.lt.ie)
        i=i+1
        if (string(i:i).ge.'0' .and. string(i:i).le.'9') then
          if (exp_pt.eq.0) then
            m=m*10 + ichar(string(i:i))-48
            if (dcm_pt.eq.1) then
              n=n*10
            elseif (dcm_pt.gt.1) then
              ierr=ierr+1
            endif
          elseif (exp_pt.eq.1) then
            k=k*10 + ichar(string(i:i))-48
          elseif (exp_pt.gt.1) then
            ierr=ierr+1
          endif
        elseif (string(i:i).eq.'.') then
          dcm_pt=dcm_pt+1
        elseif (string(i:i).eq.'E' .or. string(i:i).eq.'D' .or.
     &          string(i:i).eq.'e' .or. string(i:i).eq.'d') then
          exp_pt=exp_pt+1
          if (i.lt.ie) then
            i=i+1
            if (string(i:i).eq.'+') then
              msgn=+1
            elseif (string(i:i).eq.'-') then
              msgn=-1
            else
              i=i-1
            endif
          endif
        else
          ierr=ierr+1
        endif
      enddo
      if (ierr.eq.0) then
        value=isgn*dble(m)/dble(n)
        k=10**k
        if (msgn.eq.1) then
          value=value*dble(k)
        elseif (msgn.eq.-1) then
          value=value/dble(k)
        endif
      endif
      string_to_dble=ierr
      return
      end


bjagers
Posts: 5
Joined: Tue Nov 28, 2006 5:55 pm
Location: Deltares

Re: Intel Fortran compiler bug report (this is not bug in ROMS)

#4 Unread post by bjagers »

shchepet wrote:
There are 7 such symbols:

, / F T f t
I'm not sure about the reasoning behind the first two problem characters (they might be considered field separators), but the T's and F's are interpreted by the system as representations for .TRUE. and .FALSE. Since you don't specify the format of the values to be expected, the reader accepts T and F values and converts them in -1 (all bits set) and 0 (no bits set) respectively. We encountered this problem a couple of years ago when we had problems distinguishing between filenames and values as parameters: files starting with T or F could not be used because first tried to interpret the string as a value. Now we first check whether a file exist with the name 'txyz' or '3.14' and only if that is not successful try to interpret the string as a number. Still, this gives sometimes strange error messages if an input file was forgotten or misplaced. In other sections of our code we use a similar value scanning process as the one in 'string_to_dble' to automatically distinguish between floating point values, integers, logicals, and strings.

Post Reply