I have a ByteString
that is containing the representation of Float
s. Each Float
is represented by 3 bytes in the ByteString
.
I need to do some processing on the Float
values, so I would like to perform that processing on an Vector
of Float
values. What would be the best way to do this?
I have a function toFloat :: [Word8] -> Float
that converts 3 bytes of the ByteString
to a Float. So I was thinking of iterating over the ByteString
in steps of 3 Bytes and converting every step to a Float
for a vector
.
I've looked at the library functions for Vector
but I can't find anything that suits this purpose. Data.Vector.Storable.ByteString.byteStringToVector
looked promising but it converts every byte (instead of every 3 bytes) and doesn't give me any control over how the conversion of ByteString
to Float
should happen.
Just use Data.Vector.generate
:
V.generate (BS.length bs `div` 3) $ \i ->
myToFloat (bs BS.! 3*i) (bs BS.! 3*i+1) (bs BS.! 3*i+2)
It'll allocate the vector all at once, and populate it. Data.ByteString.!
is O(1), so this is quite efficient.
Try using
splitAt :: Int -> ByteString -> (ByteString, ByteString)
to split the ByteString into two: one of exactly 3 characters, and another containing the rest of the input. You can use this to implement a recursive function that will give you all the groups of length 3 (similar to Data.List.Split.chunksOf
), and then you can use unpack
on each to get the [Word8]
you need. Pass that through your toFloat
function, and convert to a vector with Vector.fromList
.
There are a number of steps there that seem like perhaps they could be expensive, but I think probably the compiler is smart enough to fuse some of them, like the unpack/fromList pair. And splitting a ByteString is O(1), so that part's not as expensive as it looks either. Seems like this ought to be as suitable an approach as any.
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