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

1

6

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?

Talipes answered 19/12, 2013 at 7:33 Comment(0)
G
4

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.

Gradus answered 19/12, 2013 at 16:24 Comment(1)
Indeed, that does produce the correct assembly code. The whole if is unnecessary in this case, of course. But then again, this is a bit hackish solution and while it works with the current version, I don't think it is generally safe to assume it will work also in the future. Good enough for the time being, though - thanks!Talipes

© 2022 - 2024 — McMap. All rights reserved.