From: Christopher N. Vogt
Subject: binary streams and floats in CL
Date: 
Message-ID: <349875E5.5CABBA24@home.com>
I have a file full of IEEE floats.  Is there an *easy* and/or efficient
way to get these into lisp?  All I can think of is to convert them from
binary to decimal representations of the exponent and mantissa, then 
convert that into a string e.g. "1.0e0" then read from the string.

From: Raymond Toy
Subject: Re: binary streams and floats in CL
Date: 
Message-ID: <4n7m92wx7f.fsf@rtp.ericsson.se>
>>>>> "Christopher" == Christopher N Vogt <ยทยทยทยท@home.com> writes:

    Christopher> I have a file full of IEEE floats.  Is there an
    Christopher> *easy* and/or efficient way to get these into lisp?
    Christopher> All I can think of is to convert them from binary to
    Christopher> decimal representations of the exponent and mantissa,
    Christopher> then convert that into a string e.g. "1.0e0" then
    Christopher> read from the string.


I used to have code to do this, but I don't know where it went.

However, it wasn't too hard to do.  It went something like this, where 
we assume that the numbers and machine have the same endianness, and
the floats are single precision.

1.  Read in the file as 32-bit signed integers.
2.  Get the sign bit (most significant bit, obviously), S
3.  Get the next 8 bits; this is the exponent, E
4.  The remaining 23 bits is almost the fractional part, F
5.  The desired float value is then

	S * 2^(E-b) * (1 + F/2^24)


    where b is the bias in the exponent, 127, I think.

    This operation can probably be done as 

	(scale-float (float (+ (expt 2 24) f) 1.0) (- e b 24))

For double floats, just make the exponent 11 bits and the fraction 53
bits, with an implied leading 1 bit.

Ray
From: John Watton
Subject: Re: binary streams and floats in CL
Date: 
Message-ID: <uhg85cyk3.fsf@alcoa.com>
I used to do this for 32 bit integers by reading them as signed 32 bit
integers and using the following routine:

(defun fix-to-float-lisp (num)
  (let ((sign (ldb (byte 1 31) num))
	(expt (- (ldb (byte 8 23) num) 127))
	(frac (ldb (byte 23 0) num)))
    (cond ((or (< expt -126))
	   0.0)
	  ((> sign 0)
	   (- (scale-float (float (+ 8388608 frac) 1.0) (- expt 23))))
	  (t
	   (scale-float (float (+ 8388608 frac) 1.0) (- expt 23))))))


For purposes of speed I now use a foreign function call ( in ACL 4.3)
to a C routine:

(ff:defforeign 'fix-to-float-c
    :entry-point (ff:convert-to-lang "fix_to_float")
    :language :c
    :return-type :single-float
    :arguments '(integer)
    :arg-checking nil
    :call-direct nil
    :callback nil)

float fix_to_float (int value_in)
{
  union 
    {
      float float_value;
      long int  int_value;
    } value;
  value.int_value = value_in;
  return (value.float_value);
}


John Watton
Applied Math & Computer Technology
ALCOA Technical Center
From: Christopher N. Vogt
Subject: Re: binary streams and floats in CL
Date: 
Message-ID: <349A8ABB.E01E2F3D@home.com>
Thanks to all who replied.  My brain was stuck on methods I had used in the
past, including ff calls and machine dependent instructions, and I couldn't
get out of that box.