Re: reading NaNs Aubrey Jaffer 27 Oct 2005 16:45 UTC

 | Date: Tue, 25 Oct 2005 18:13:54 -0500
 | From: Alan Watson <xxxxxx@astrosmo.unam.mx>
 |
 | Aubrey Jaffer wrote:
 | > Having a universal read/write representation for arbitrary bit
 | > patterms prevents including information like the procedure
 | > causing the NaN in its printed representation.
 |
 | I don't see this. Can you elaborate?

Suppose Scheme implementation X distinguishes NaNs by the procedure
producing them and makes that information part of the printed
representation for NaNs:

  (expt +inf.0 0)    ==>  #<not-a-number expt>
  (+ -inf.0 +inf.0)  ==>  #<not-a-number +>
  (/ (* 0 -inf.0) 3) ==>  #<not-a-number *>
  (+ 5. (/ 0.0 0.0)) ==>  #<not-a-number />

If R6RS has a universal read/write representation for arbitrary bit
NaN patterns, then R6RS must assign bit patterns for all possible
#<not-a-number {*}> syntaxes.  If some future IEEE-754 hardware
returns more than one NaN code, then its assignments are very unlikely
to match the R6RS codes.

Scheme has so far avoided arbitrary assignments of numbers to
procedures.

 | BTW, I neither favor nor oppose reading or writing of arbitrary bit
 | patterns.  I am favor of being able to specify the precision of the
 | NaN, though.

The precision available in NaNs is a hardware attribute.  How can it
be settable?

 | >  | However, I still think we need a read syntax.  Suppose program
 | >  | A calculates a value and writes it to a file and program B
 | >  | reads the value from the file and uses it.  Is is not useful
 | >  | for program A to be able to communicate to program B that it
 | >  | got a NaN?
 | >
 | > [...]
 | >
 | > If program A writes out its state, it would be useful to see that
 | > NaNs were computed.  It gives operators a chance to capture the
 | > use case which provoked the error.  If the program state is very
 | > valuable, then it can be repaired manually.
 | >
 | > But if program B reads its initial state from the file, its
 | > reading of NaNs puts errors into its state which can propagate
 | > and corrupt it.
 |
 | Um, how about program B doing:
 |
 |    (let ((x (read)))
 |      (if (nan? x)
 |        (display "Help! Help! Program A is feeding me NaNs!")))
 |
 | Sure, if you don't check your input, you can be screwed, but what's
 | new there?

If program B reads lists, association lists, or vectors containing
numbers, then your approach must descend data structures looking for
NaNs -- all this effort for a case which shouldn't occur.  Should this
input vetting also check for embedded end-of-file objects?

One could use NaNs for all sorts of purposes.  I think they are most
useful when they flag impossible and unplanned-for numerical errors.
As such, it removes this input vetting burden if an implementation is
permitted to make NaNs unreadable.

 | Another example. Astronomical detectors tend to have a fair number
 | of bad pixels. We normally deal with these by associating a binary
 | "bad pixel map" with each image. The images are initially fixnums,
 | but after initial processing they are converted to flonums. It is a
 | lot simpler to simply replace the bad pixels in the processed
 | images with NaNs rather than continuing to work with the bad pixel
 | maps. I want to be able to archive processed images, so I need to
 | be able to read and write NaNs.  (Okay, this is a bit of a cheat,
 | because the data are written in a binary format, but my point is
 | the same: reading a NaN is not necessarily an error.)

If NaNs were used to signal bad pixels, then those NaNs would spread
to neighboring pixels with certain types of signal processing steps.
If you happened to employ Fourier transforms to do convolutions, then
your entire image would become NaNs.