I have an array of (unsigned-byte 32)
that contains quite a bit of data, some of it in floating point format. That is, some of the bytes are handled as integers containing bit fields, while some of them as 32-bit floating point numbers.
I need to both read and write the data in the array.
Unfortunately, the function sb-kernel:make-single-float
takes in an argument of (signed-byte 32)
, and sb-kernel:single-float-bits
returns a signed word as well, so they are not directly compatible with my vector. On the other hand, converting the vector to contain signed bytes would make the bit field operations painful.
This far, I have written
(defun u32-to-sf (x)
(declare (optimize (speed 3) (compilation-speed 0) (debug 0))
(type (unsigned-byte 32) x))
(if (>= x #x80000000)
(sb-kernel:make-single-float (- x #x100000000))
(sb-kernel:make-single-float x)))
which does the correct thing, but the generated assembly does look ugly with its conditional jump and unnecessary comparisons and subtractions.
Any ideas on how to convince sbcl to simply accept the bitwise contents of the unsigned-byte
as the bitwise contents for the float-to-be?
You might (declare (optimize (safety 0)) (type (signed-byte 32) x)))
. That seems to produce much shorter assembly (it even optimizes the unused if
branch away) and the same results. I would propose to really scrutinize the assembly and to secure this with thorough regression tests, though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With