2

I want to store a vector of integers (uint8) as (space-)efficiently as possible in MATLAB. So far, I am using arithenco to encode the vector:

bits = arithenco(z, counts);

The good thing is that it returns a vectors of bits. The bad thing is that the bits are stored in doubles. This means that the returned vector is about 64 times as large as the original uint8 vector, while the whole idea was to make the thing smaller.

So is there an easy (and runtime-efficient) way to encode those pseudo-bits so that I actually get a space improvement?

The only solution I've come up with yet is to use bitset to store all those bits in a vector of, say, uint32 again, but this seems to be cumbersome and not very fast as I will have to loop over the whole bits vector explicitly.

Note: I can not use the Java API for this, otherwise this would have been relatively easy.

3 Answers 3

3

Similar to your solution, but using core MATLAB functions only:

%# some random sequence of bits
bits = rand(123,1) > 0.5;

%# reshape each 8 bits as a column (with zero-padding if necessary)
numBits = numel(bits);
bits8 = false(8, ceil(numBits/8));
bits8(1:numBits) = bits(:);

%# convert each column to uint8
bits_packed = uint8( bin2dec(char(bits8'+'0')) );

Compare the sizes:

>> whos bits bits_packed
  Name               Size            Bytes  Class      Attributes

  bits             123x1               123  logical              
  bits_packed       16x1                16  uint8          

To unpack/recover the original bits:

%# unpack
b = logical(dec2bin(bits_packed)' - '0');
b = b(:);

%# sanity check
isequal(bits, b(1:numBits))
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! I didn't think about character conversion. I guess this could even be faster than my solution.
1

After some searching and trying, I've finally come up with this solution:

bitCount = size(bits, 2);
bits8 = zeros(ceil(bitCount/8), 8);
bits8(1:bitCount) = bits;           % Reshape to (pseudo-)8-bit representation
comp = uint8(bi2de(bits8));         % Convert to efficient byte representation

The key part here is the bi2de function which "converts a binary row vector b to a nonnegative decimal integer". To get the bits again, the de2bi function can be used.

4 Comments

If this is the complete answer you were looking for, you can mark it as accepted even if you're the one who answered it.
@rolve: shouldn't bits8 be defined as: bits8 = zeros(8,ceil(bitCount/8)); so that it gets filled in the correct order (by columns). Just remember to transpose before passing it to bi2de
@Amro yeah, you're probably right. However, since i just want to store the bits efficiently, it does not matter whether they're in the rows or spread across the columns. I just have to do the right reshaping when converting them back into the ?-bit representation.
@rolve: I guess you're right, you got my +1 vote anyways.. By the way I posted a solution similar to yours but without using any special toolboxes.
0

You can convert them to logical:

     bitsLogical = logical(bits);

This should be more efficient in memory. But you will still have the conversion step. So the best thing is to dive into arithenco and change it to return logical in the first place.


Edit As the OP says correctly, this will not be packed as bits, but as bytes. Still it is an improvement over double.

3 Comments

Thank you for the idea but logicals are stored as bytes, so there are still 7 out of 8 bits wasted.
@rolve, I did not know it. Do you have any reference for this?
You can check the size of your data structures with the whos (mathworks.ch/help/techdoc/ref/whos.html) command. Using that you will see that a single logical has a size of 1 byte.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.