Concatenating multiple cells in a single matrix

3 visualizaciones (últimos 30 días)
Abdallah Talafhah
Abdallah Talafhah el 9 de Jun. de 2021
Comentada: Abdallah Talafhah el 22 de Jun. de 2021
I'm trying to hide files in a float64 DCT2 array; I have the stream of bits in a single 1*x array where each cell includes a single bit. I'm already able to concatenate bits into bytes successfully by using a for loop, 8 placeholder variables, and strcat.
for col = 1 : 8 : bitStreamSize(2) - 7
bit0 = bitStream(1,col);
bit1 = bitStream(1,col + 1);
bit2 = bitStream(1,col + 2);
bit3 = bitStream(1,col + 3);
bit4 = bitStream(1,col + 4);
bit5 = bitStream(1,col + 5);
bit6 = bitStream(1,col + 6);
bit7 = bitStream(1,col + 7);
result = strcat(num2str(bit0),num2str(bit2),num2str(bit2),num2str(bit3),num2str(bit4),num2str(bit5),num2str(bit6),num2str(bit7));
result = bin2dec(result);
file(1,((col - 1)/8) + 1) = result;
end
This works fine for when you know how many bits you're dealing with, but now I want to do the same thing somewhere else in my project where the user inputs a number from 1 to 63 and then that number of bits will be concatenated into a single cell. I thought of using a switch statement but MATLAB does not use break; like C++ so I'd have to repeat the code 63 times; this would be a very clunky implementation and it'd be very hard to modify.
Is there a more effecient/modular way of concatenating a given number of bits without having to redo everything for every single possible number?
  2 comentarios
Jan
Jan el 9 de Jun. de 2021
Editada: James Tursa el 9 de Jun. de 2021
This is not valid Matlab code:
file = (1,((col - 1)/8) + 1) = result;
Abdallah Talafhah
Abdallah Talafhah el 15 de Jun. de 2021
I was copying code offhand from another PC so I mess up; I updated the original post.

Iniciar sesión para comentar.

Respuesta aceptada

Jan
Jan el 9 de Jun. de 2021
Editada: Jan el 18 de Jun. de 2021
The conversion from numeric to string and back to numeric is an expensive indirection.
n = 8;
% p = uint64(2).^(0:n-1); % LSB
p = uint64(2).^(n-1:-1:0); % MSB
file = [];
for col = 1 : n : bitStreamSize(2) - (n - 1)
result = uint64(0);
for k = 0:n-1
result = result + uint64(bitStream(col + k) * p(k + 1));
end
file(end + 1) = result; % Bad: iteratively growing array
end
This can be done faster and nicer without a loop:
n = 8; % Number of bits
B = reshape(bitStream, n, []);
% C = uint64(B) .* bitshift(uint64(1), 0:n-1).'; % LSB
C = uint64(B) .* bitshift(uint64(1), n-1:-1:0).'; % MSB
file = sum(C, 1, 'native');
This uses auto-expanding introduced in Matlab R2016b. With older versions:
C = bsxfun(@times, uint64(B), bitshift(uint64(1), 0:n-1).');
Matlab R2018b does not support a matrix multiplication of UINT64 arrays. If your data has less then 53 bits, you can work with doubles and the code gets really compact:
n = 8; % Number of bits, n <= 52
file = bitshift(1, n-1:-1:0) * reshape(bitStream, n, []); % MSB
  3 comentarios
Jan
Jan el 16 de Jun. de 2021
Editada: Jan el 16 de Jun. de 2021
"Niether of these worked;"
My first version cannot run at all, because I could not understand, what this line of your code should do:
file = (1,((col - 1)/8) + 1) = result;
You have fixed this line after I've posted my answer. So please do not blame me to post not working code.
I cannot guess, how you have created
file = [178,130,42;2,0,0;4,0,0;8,0,0;16,0,0;32,0,0;64,0,0;128,0,0]
if you do not show the code you have used. My code did not create the variable file.
With this code, I get [178,130,42] as output:
bitStream = [0,1,0,0,1,1,0,1,0,1,0,0,0,0,0,1,0,1,0,1,0,1,0,0];
bitStreamSize = size(bitStream); % Educated guessing...
n = 8;
p = 2.^(0:n-1);
file = [];
for col = 1 : n : bitStreamSize(2) - (n - 1)
result = uint64(0);
for k = 0:n-1
result = result + uint64(bitStream(col + k) * p(k + 1));
end
file(end + 1) = result;
end
I cannot confirm, that my 2nd method produces an error. Whenever you mention an error in the forum, post a copy of the complete message instead of a rough paraphrasing. An error concering the "matrix multiplication" is unlikely, because my code does not contain a matrix multiplication, but an elementwise mutliplication of arrays. This uses an auto-expanding, which was introduced in Matlab 2016b. Which Matlab version are you using? Did you forget the dot in .* ?
The order of the bits can be changed easily in my code:
p = 2 .^ (0:n-1); % LSB
p = 2 .^ (n-1:-1:1); % MSB
5 times faster with bitshifting instead of the expensive power operation:
p = bitshift(uint64(1), 0:n-1); % LSB
p = bitshift(uint64(1), n-1:-1:0); % MSB
My 2nd code with MSB:
n = 8;
B = reshape(bitStream, n, []);
C = uint64(B) .* bitshift(uint64(1), n-1:-1:0).';
file = sum(C, 1, 'native')
This replies [77, 65, 84] as wanted.
I've modified my answer to consider the bit order.
Claiming, that code provided by voluntary helpers is not working, sounds less polite than saying "thanks".
Abdallah Talafhah
Abdallah Talafhah el 22 de Jun. de 2021
Adamantly, I didn't give you all the info you need to give me a solution that'd work right away.
The problem with the .* is that I'm using version R2014a and thankfully you included a solution using the bsxfun function.
I adapted it to use MSB like so:
C = bsxfun(@times, uint64(B), bitshift(uint64(1), n-1:-1:0).');
Thanks for your time

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Más información sobre Startup and Shutdown en Help Center y File Exchange.

Productos


Versión

R2014a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by