Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sbcl: converting (unsigned-byte 32) into single-float

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?

like image 725
jlahd Avatar asked Dec 19 '13 07:12

jlahd


1 Answers

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.

like image 147
Svante Avatar answered Oct 05 '22 03:10

Svante