Question

I have this code:

close, 1 & openr,1,filename,error=err
if (err ne 0) then begin
   close, 1
   n=0
   return
endif

line=fltarr(41)

while(not(eof(1))) do begin
   readf,1,line
endwhile

And on the line readf,1,line I get the following error:

READF: End of file encountered. Unit: 1, File: results
Program caused arithmetic error: Floating illegal operand

I see what the cause is and I read the docs about it, but I still don't understand what arithmetic error has to do with EOF (why EOF? I checked if not(eof(1))) and what to do to get rid of this error. Do you have any ideas?

Was it helpful?

Solution

The illegal floating point operation is probably not from not(eof(1)) but from readf, 1, line or carried over from another portion of the code.

IDL is expecting to read in 41 32-bit float values, but some or all of the values it reads in are not valid floating point numbers. Not all 32-bit series of 1s and 0s make a valid IEEE float32 (the "float" values used in IDL and most other languages). If you inadvertently encounter the end of the file, there's a high chance that some of the data read from the file won't fit nicely into a float32. When that happens, IDL will attempt to make an informed guess as to which float number your data should have been, but doing so is not technically part of the IEEE standard, so it raises the Program caused arithmetic error: Floating illegal operand error.

To investigate, you might like to try substituting the following code:

close, 1 & openr, 1, filename, error=err
if (err ne 0) then begin
   close, 1
   n = 0
   return
endif

line = bytarr(41 * 4)

while not(eof(1)) do begin
   readf, 1, line
endwhile

In this case, because you are reading into a byte array instead of a float array, the only error should be READF: End of file encountered. Unit: 1, File: results.

Another possible issue is the use of not(eof(1)), which is non-standard. In IDL, not is the bit-wise not, meaning it inverts all the bits of the next term. The more appropriate operator here would be "logical not", ~. Thus instead of not(eof(1)) or not eof(1), consider using ~eof(1). In this particular case, it's unlikely to matter, since eof should return either 1B or 0B, the bit-wise inverse of which are identical to the logical inverse. All the same, it's another thing to try which debugging.

Finally, it's possible that the Floating illegal operand error is actually being caused before the READF: End of file encountered error. As unintuitive as this is, consider the following block of code:

x = sqrt(-1.0)
print, 'Hello, World.'

This outputs:

Hello, World.
% Program caused arithmetic error: Floating illegal operand

Notice that Hello, World. printed before the floating point illegal operand error. That's because IDL doesn't actually report floating point errors until either a function returns, the program ends/crashes, or the check_math() function is called. To check if your program is generating the floating point error before this block, place print, check_math() at the top of the code block. If doing so prints anything besides 0, then floating point errors occurred before the block. Using check_math() also resets these error states, so you can inhibit the floating point error messages by placing math_err = check_math() after each statement which might cause a floating point error.

Here is a modified version of your original code which might handle all the errors above:

math_err = check_math()  ; remove any lingering floating point errors

close, 1
openr, 1, filename, error=err
if err ne 0 then begin
    close, 1
    n = 0
    return
endif

line = fltarr(41)

catch, err  ; return here if a non-math error happens
if err ne 0 then begin

    catch, /cancel  ; prevent infinite loop between catch and message
    if !error_state.name eq 'IDL_M_FILE_EOF' then begin
        ; Handle premature end-of-file here.
    endif else begin
        message, /reissue_last  ; issue non-eof errors normally
    endelse

endif else begin

    while ~eof(1) do begin
        readf, 1, line
        ; Handle new line here.
    endwhile
    catch, /cancel  ; stop error checking

endelse

OTHER TIPS

You probably don't have an even number of 41 floats in the file. Every call to readf, 1, line will try to read in enough data to fill line. Instead of eof(), you could use fstat() and the size of a float to determine if there's enough data in the file to read a line.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top