Question

I have a vector containing the values 0, 1, 2 and 3. What I want to do is take the lower two bits from each set of 16 elements drawn from this vector and append them all together to get one uint32. Anyone know an easy way to do this?

Follow-up: What if the number of elements in the vector isn't an integer multiple of 16?

Was it helpful?

Solution

Here's a vectorized version:

v = floor(rand(64,1)*4);
nWord = size(v,1)/16;
sum(reshape([bitget(v,2) bitget(v,1)]',[32 nWord]).*repmat(2.^(31:(-1):0)',[1 nWord ]))

OTHER TIPS

To refine what was suggested by Jacob in his answer and mtrw in his comment, here's the most succinct version I can come up with (given a 1-by-N variable vec containing the values 0 through 3):

value = uint32(vec(1:16)*4.^(0:15)');

This treats the first element in the array as the least-significant bit in the result. To treat the first element as the most-significant bit, use the following:

value = uint32(vec(16:-1:1)*4.^(0:15)');

EDIT: This addresses the new revision of the question...

If the number of elements in your vector isn't a multiple of 16, then the last series of numbers you extract from it will have less than 16 values. You will likely want to pad the higher bits of the series with zeroes to make it a 16-element vector. Depending on whether the first element in the series is the least-significant bit (LSB) or most-significant bit (MSB), you will end up padding the series differently:

v = [2 3 1 1 3 1 2 2];  % A sample 8-element vector
v = [v zeros(1,8)];  % If v(1) is the LSB, set the higher bits to zero
% or...
v = [zeros(1,8) v];  % If v(1) is the MSB, again set the higher bits to zero

If you want to process the entire vector all at once, here is how you would do it (with any necessary zero-padding included) for the case when vec(1) is the LSB:

nValues = numel(vec);
nRem = rem(nValues,16);
vec = [vec(:) zeros(1,nRem)];  % Pad with zeroes
vec = reshape(vec,16,[])';  % Reshape to an N-by-16 matrix
values = uint32(vec*4.^(0:15)');

and when vec(1) is the MSB:

nValues = numel(vec);
nRem = rem(nValues,16);
vec = [vec(1:(nValues-nRem)) zeros(1,nRem) ...
       vec((nValues-nRem+1):nValues)];  % Pad with zeroes
vec = reshape(vec,16,[])';  % Reshape to an N-by-16 matrix
values = uint32(fliplr(vec)*4.^(0:15)');

I think you should have a look at bitget and bitshift. It should be possible to be something like this (pseudo-matlab code as I haven't worked with Matlab for a long time):

result = 0;
for i = 1:16 do
  result += bitshift(bitget(vector(i), 2:-1:1), 2);

Note that this will give you the last bits of the first vector in the highest bits, so you might want to descend i from 16 to 1 instead

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top