Concatenating multiple cells in a single matrix

3 ビュー (過去 30 日間)
Abdallah Talafhah
Abdallah Talafhah 2021 年 6 月 9 日
コメント済み: Abdallah Talafhah 2021 年 6 月 22 日
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 件のコメント
Jan
Jan 2021 年 6 月 9 日
編集済み: James Tursa 2021 年 6 月 9 日
This is not valid Matlab code:
file = (1,((col - 1)/8) + 1) = result;
Abdallah Talafhah
Abdallah Talafhah 2021 年 6 月 15 日
I was copying code offhand from another PC so I mess up; I updated the original post.

サインインしてコメントする。

採用された回答

Jan
Jan 2021 年 6 月 9 日
編集済み: Jan 2021 年 6 月 18 日
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 件のコメント
Jan
Jan 2021 年 6 月 16 日
編集済み: Jan 2021 年 6 月 16 日
"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 2021 年 6 月 22 日
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

サインインしてコメントする。

その他の回答 (0 件)

カテゴリ

Help Center および File ExchangeStartup and Shutdown についてさらに検索

製品


リリース

R2014a

Community Treasure Hunt

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

Start Hunting!

Translated by