Re: floating-point-bits

"David McClain (as dbm at refined-audiometrics dot com)" <[email protected]>
Newsgroups gmane.lisp.lispworks.general
Message-ID <[email protected]>
So here is the problem…

A stream of bytes is transmitted, representing 4 arrays of 12 elements of single-floats. On the Lisp side READ-SEQUENCE only accepts a Lisp vector to read into. You can probably substitute a TYPED-AREF-VECTOR there, as it is really an array of DOUBLE-FLOAT. And luckily, the dimensions work out to an equivalent number of double-floats in length. I may, or may not have tried that already. As it now reads, I use an array of (UNSIGNED-BYTE 8) for the receiver array.

Then to get use of the Chimera Union type, I have to copy the contents of a receiver vector into an FLI array, then copy back to a float array for access by the float clients.So, you might say - two copy operations, big deal. And you would be correct. But this is two more than seems necessary had the original receiver array been capable of supporting a Union type.

Now that I have discovered FLI:WITH-DYNAMIC-LISP-ARRAY-POINTER I may have a better approach without copying. Or maybe not...

Currently, my read loop looks like the following:

(fli:define-foreign-type chimera (nf)
  `(:union
    (ubv  (:c-array :uint8 (* ,nf 4)))
    (sfv  (:c-array :float ,nf))))



    (let ((ubvec  (make-array #.(* 4 12 4)
                               :element-type '(unsigned-byte 8)))
           (fpvec  (make-array #.(* 4 12)
                               :element-type 'single-float))
(cond
                              ((eql #.(* 4 12 4) (read-sequence ubvec sock))
                               (fli:with-dynamic-foreign-objects ((p (chimera #.(* 4 12))))
                                 (let ((ubv  (fli:foreign-slot-pointer p 'ubv))
                                       (sfv  (fli:foreign-slot-pointer p 'sfv)))
                                   (fli:replace-foreign-array ubv ubvec)
                                   (fli:replace-foreign-array fpvec sfv)
                                   ))
                               (send cust :ok))
                              
                              (t
                               (send fmt-println "Connection timeout.")
                               (send self cust :finish))
                              )

> On Feb 15, 2025, at 11:48, David McClain <[email protected]> wrote:
> 
> Not trolling… my mouth waters at such a prospect. Lucky you !!!
> 
> 
>> On Feb 15, 2025, at 11:29, Bradford Miller <[email protected]> wrote:
>> 
>> What, are you trolling those of us who used Lisp Machines?
>> 
>>> On Feb 15, 2025, at 1:17 PM, David McClain (as dbm at refined-audiometrics dot com) <[email protected]> wrote:
>>> 
>>> But then, again, I don’t think Lisp was ever envisioned as a Systems Programming Language…
>>> 
>>> 
>>>> On Feb 15, 2025, at 11:16, David McClain <[email protected]> wrote:
>>>> 
>>>> I actually have this exact situation, but not between two Lisp systems. Rather, my remote telemetry system generates data from an embedded C-based audio plugin, and transmits it across a TCP link to clients which run Lisp-based analysis code and remote displays.
>>>> 
>>>> So, the problem I actually face is that I need to transmit IEEE 754 single-precision floating point data to Lisp. I think today we can count on every computer in the system supporting IEEE 754 standard data format, whereas it seems that historically Lisp dates from an era before IEEE 754 and may have heterogeneous custom formats for floating point, as evidenced by SHORT-FLOAT, SINGLE-FLOAT, DOUBLE-FLOAT, and LONG-FLOAT offerings.
>>>> 
>>>> But what is frustrating is that while it is easy to stream single-float across the TCP connection as a stream of bytes, Lisp does not have the complementary notion of C-Union types that the transmitter has, and reassembling the float data on the Lisp side takes too much unnecessary bit banging to reassemble the floats.
>>>> 
>>>> I have partially solved this problem by appealing to the LW FLI and defined a Chimera UNION type that represents both an array of bytes and a single-float. But TYPED-AREF-VECTORS cannot be defined on this Chimera type.
>>>> 
>>>> So it is confounding that Lisp, for all of its amazing capabilities, has never thought it necessary to represent Union types.
>>>> 
>>>> - DM
>>>> 
>>>>> On Feb 15, 2025, at 10:24, Paul Werkowski (as pw at snoopy dot qozzy dot com) <[email protected]> wrote:
>>>>> 
>>>>> I came across the chapter in the LW UG about TYPED-AREF-VECTOR and friends. It reminded me of a project a long time ago where I wanted to stream real-time floating-point data over a TCP communication link to an analysis client. I came up with code to pack/unpack FP data. Maybe someone would find it useful.
>>>>> 
>>>>> ;;; fp-bits.lisp
>>>>> 
>>>>> ;;;;;;;;;;;;;;;;;;;;;;
>>>>> (defun single-float-bits (fpn)
>>>>> (declare (type single-float fpn))
>>>>> ;; 1.5 == 0x3fc00000
>>>>> ;; signif  #x0c00000
>>>>> ;; expon -23
>>>>> (multiple-value-bind (signif expon sign)
>>>>>   (integer-decode-float fpn)
>>>>> (let* ((sgn (if (minusp sign) 1 0))
>>>>>        (exp (+ 127 expon 23)) ; 23 bits?
>>>>>        (man (ldb (byte 23 0) signif)) ; 0x400000
>>>>>        (bits exp))
>>>>>   (setf bits (dpb sgn (byte 1 31) bits)
>>>>>         bits (dpb exp (byte 8 23) bits)
>>>>>         bits (dpb man (byte 23 0) bits))
>>>>>   bits)))
>>>>> 
>>>>> (defun make-single-float (bits)
>>>>> (declare (type (unsigned-byte 32) bits))
>>>>> (let* ((sgn (ldb (byte 1 31) bits))
>>>>>      (exp (ldb (byte 8 23) bits))
>>>>>      (mant (ldb (byte 23 0) bits))
>>>>>      (signif (logior mant #x800000)) ; (ash 1 23)
>>>>>      (sign (if (= sgn 1) -1f0 1f0))
>>>>>      (expon(- exp 150)))
>>>>> (float-sign sign (scale-float (float signif) expon))))
>>>>> 
>>>>> (defun double-float-bits (dfn)
>>>>> (declare (type double-float dfn))
>>>>> (multiple-value-bind (signif expon sign)
>>>>>   (integer-decode-float #+()decode-float dfn)
>>>>> (let* ((sgn (if (minusp sign) 1 0))
>>>>>        (exp (+ 1023 expon 51 )) ; ?
>>>>>        (man (ldb (byte 52 0) signif))
>>>>>        (bits exp))
>>>>>   (setf bits (dpb sgn (byte 1 63) bits)
>>>>>         bits (dpb exp (byte 11 52) bits)
>>>>>         bits (dpb man (byte 52 0) bits))
>>>>>   bits)))
>>>>> 
>>>>> (defun make-double-float (bits)
>>>>> (declare (type (unsigned-byte 32) bits))
>>>>> (let* ((sgn  (ldb (byte  1 63) bits))
>>>>>      (exp  (ldb (byte 11 52) bits))
>>>>>      (mant (ldb (byte 52 0) bits))
>>>>>      (signif (logior mant (ash 1 52)))
>>>>>      (sign (if (= sgn 1) -1d0 1d0))
>>>>>      (expon(- exp 1023 51)))
>>>>> (float-sign sign (scale-float (float signif) expon))))
>>>>> 
>>>>> ;;;;;;;;;;;;
>>>>> 
>>>>> _______________________________________________
>>>>> Lisp Hug - the mailing list for LispWorks users
>>>>> [email protected]
>>>>> http://www.lispworks.com/support/lisp-hug.html
>>>> 
>>> 
>>> 
>>> _______________________________________________
>>> Lisp Hug - the mailing list for LispWorks users
>>> [email protected]
>>> http://www.lispworks.com/support/lisp-hug.html
>> 
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.