Floating exception error on PC linux

I need to compile code with fpe enabled to trap bad data and so use -Ktrap=fp. I then find that the following lines work fine, ie no fpes generated:
integer maxint, i
real myreal
maxint=2147483647 (2**31 - 1)
i=maxint
write(,) i

The following code(s) generate an fpe… Why? Am I missing something?
integer maxint, i
real myreal
maxint=2147483647
i=ifix(maxint1.0)
write(
,) i
and
integer maxint, i
real myreal
maxint=2147483647
i=ifix(maxint
1)
write(,) i

Hope someone can let me have a solution… I need to have fpes enabled and want to convert a real to and interger and write it to sdtout. If it’s larger than 2^31-1, then truncate it and then write it out using ifix or nint or some other way. Thanks in advance - Vic

Hi Vic,


First the bad news. In standard F95, exception handling is not supported. It is part of the F2003 standard, but as of yet pgf90 does not support F2003. “-Ktrap=fp” will trap floating point exceptions, but halts execution if one occurs. So you’ll need to devise a different method to accomplish this.

As for your seeing the floating point exception when calculating ifix. ifix converts a real to integer by truncating the real to a single precision real (32-bits) and then stores the value as a 32-bit integer. However, single precision reals use 1 bit for the sign, 8 bits for the exponent, and 23 bits for the mantissa (Note that there is an implied ‘1’ so the mantissa can be thought to have 24 bits). This means that the value 231-1 can not be exactly represented as single precision real and is rounded by the hardware to 231. This is causing the floating point exeception. Note, you can use pgdbg to walk through the assembly instructions and see how the values change in the x87 registers and where the exception occurs.

The largest actual integer you’ll be able to use is 2147483392 (231-255). To determine this take the hex value of 231-1, 0x7FFFFFFF and mask the last byte to account for the 23-bit mantissa to get 0x7FFFFF00. So instead of using exception handling, we can modify your program to test the data before its used, or use the minimum value if the actual value is too large.

Example:

       real rmyreal, rmaxint
       integer i
       rmaxint = (2**31)-255
       rmyreal = (2**31)-1
       write(*,*) rmaxint, rmyreal

! First method, test the data before its used
       if (rmyreal .gt. rmaxint) then
         write(*,*), 'Bad Data'
       else
         i=int(rmyreal)
         write(*,*), i
       end if

! Second method, use the smaller of the values
       i = int (amin1(rmyreal, rmaxint))
       write(*,*), i
       end

Hope this helps!
Mat

Thanks Mat, it’s clear as a bell now! - Vic