How to assign a big stream bit into one column vector - matlab

I have a large bit stream. (e.g. 10110001010101000.....001 size thousands or millions)
I want to assign this bit stream into a one column vector x.
x = zeros(n,1);
I have tried to use some mod or rem operations, there will have some problems.
I guess it caused by the integer size.
I want to ask is there any good method to solve this problem?
Thanks for reading.

Assuming, for example:
x = '10100101010101010100';
You could turn it into a logical column vector this way:
x = (x == '1')';

You can also use a simple subtraction trick with the ascii value of 0 -
x-'0'
Sample run -
>> x =
00101011001
>> x-'0'
ans =
0 0 1 0 1 0 1 1 0 0 1
Then, transpose the matrix to get a column vector - [x-'0']'.

Consider addressing the problem earlier in the processing, at load time. Each '0'/'1' character is stored as a byte, so load bytes (unsigned chars or uchar) which contain the character codes, then convert the character codes to the right 0/1 values:
fid = fopen('binchars.txt','r');
digits = fread(fid,'uchar') - 48
fclose(fid);

Related

removing uniform columns in MATLAB

Say i have a 2D matrix A:
A = [ 1 1 0 0
1 0 0 0
1 1 1 0];
A is not necessarily binary, or even integer (i.e., floats are possible). I want to remove any column that contains uniform valued elements. In the above example, i would get:
1 0
0 0
1 1
To make this fully general, i'd like to allow the user to select the dimension along which rows/columns/slices are removed (i.e., with a DIM option).
Any ideas?
You could try using the min and max functions, which allow you to use the dim argument.
For example
index = min(A,[],1)==max(A,[],1);
A(:,index)=[];
will remove the columns you want. It is straightforward to do the same for rows
index = min(A,[],2)==max(A,[],2);
A(index,:)=[];
One-liner:
B = A(:,range(A)~=0); %//columns
The other one-liner is not that nice, and ugly one-liners should not be written down. :-) But is basically the same solution as S..'s, except is way more expensive (requires stats toolbox).
Please note that "generality" of subscript-based solutions doesn't extend to N-dimensional arrays as easily, because subscripting in ND arrays without checking beforehand the number of dimensions is difficult. Also, for the 1D arrays the notion of "uniformity" is a bit odd along the singleton dimension (the result is always empty).
Besides the neat solution provided by #S.. there is this simple hack also for your example:
for ii = 1:size(A,2)
T(ii) = all(A(:,ii) == sum(A(:,ii))/numel(A(:,ii)));
end
A(:,~T)
ans =
1 0
0 0
1 1
As suggested by #gariepy the right side of the equation can be replaced with mean function.
for ii = 1:size(A,2)
T(ii) = all( A(:,ii) == mean(A(:,ii)) );
end
A(:,~T)
A(:,~all(A == repmat(A(1,:),[size(A,1) 1])))
Inspired by #S.. but only checks if every element of the column equals the first element of the column. Seems like a little less work for the processor than finding the min and the max, and checking for equality.

MATLAB: playing 16-bit audio

I have a matrix (n,16) filled with audio samples of 16 bits each.
So the matrix could look like:
[0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1; 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1]
and so on. How can i actually play this as sound? sound() is using double floating points (from -1 to 1 values). If i could just convert it to those values, I guess it would work, but im not sure. Any suggestions?
#AnderBiguri pretty much nailed it. Take your array, convert it to signed double, normalize and play it.
As you have a n x 16 matrix, where each row is a sample and each column is a bit for that number, first we need to convert that matrix into double format. We can use bin2dec to help us to do that. However, bin2dec takes in a string. As such, we can convert our matrix into a string array like so. Let's assume that inSound contains your sound matrix that you specified before.
I will also assume that your bits are in Big-Endian format, so the most significant bit is the left most bit, following down to the right most bit.
According to your comments, the numbers are signed 1's compliment. This means that should the most significant bit be 1, we simply invert the entire number. As such, we can figure out which rows are negative by checking the entire first column to see if there is a 1 or 0. We find the rows with 1 and simply take 1 and subtract every single element in the array. As such:
checkSign = inSound(:,1) == 1;
inSound(checkSign,:) = 1 - inSound(checkSign,1);
Therefore, when we convert our number to decimal, we simply find those rows again that should be negative and simply negate them. Let's convert our numbers first.
inSoundString = char(inSound + '0');
char converts each number in a matrix or vector into its string representation, assuming that the input into char is an ASCII code. As such, when we add with 0, we are adding each number in inSound with the numerical ASCII code that is representative of what 0 is in ASCII. This is our baseline to start with. After that, inSound will add either 0 or 1 to this numerical code so that when we convert this whole matrix into a string, we will finally get the string representation of those numbers.
Now convert the binary strings into actual numbers:
outSoundDec = bin2dec(inSoundString);
This will take each row and convert it into its decimal equivalent. Now, if your bits are in Little-Endian, you can use swapbytes to flip the bits so that you can transform the bits to Big-Endian before proceeding. Now that we have converted our numbers, we need to negate those rows that were supposed to be negative.
As such:
outSoundDec(checkSign) = -outSoundDec(checkSign);
Now we need to normalize this so that the range is between -1 to 1. Given that you have specified that the range is between [-32768, 32767], we simply divide all of our numbers by 32768. Therefore:
outSound = outSoundDec / 32768;
The above code will now normalize your signal so that it goes from -1 to 1. You can use sound(outSound, Fs); to play your sound where Fs is the sampling frequency your signal was obtained at.
Good luck!

Appending "in a way" multiple matrices

Say I have matrices A and B. I want to create a third matrix C where
A = [1,0,0,1]
B = [1,0,1,0]
C = [11, 00, 01, 10]
Is there such a function in Matlab? If not how would I go about creating a function that does this?
Edit: C is not literal numbers. They are concatenated values of A,B element-wise.
Edit2: The actual problem I am dealing with is I have 10 large matrices of the size [x,y] where x,y > 1000. The elements in these matrices all have 0s and 1s. No other number. What I need to accomplish is have the element [x1,y1] in matrix 1 to be appended to the element in [x1,y1] of matrix 2. and then that value to be appended to [x1,y1] of matrix 3.
Another example:
A = [1,1,1,1;
0,0,0,0]
B = [0,0,0,0;
1,1,1,1]
C = [1,0,1,0;
0,1,0,1]
And I need a matrix D where
D = [101, 100, 101, 101; 010, 011, 010, 011]
I recommend that you avoid manipulating binary numbers as strings where possible. It seems tempting, and there are cases where matlab provides a more elegant solution if you treat a binary number as a string, but you cannot perform binary arithmetic on strings. You can always work with integers as if they were binary (they are stored as bits in your machine after all), and then just display them as binary numbers using dec2bin when necessary.
A = [1,0,0,1]
B = [1,0,1,0]
C = bitshift(A,1)+B;
display(dec2bin(C));
In the other case you show in your question you could use:
A = [1,1,1,1; 0,0,0,0];
B = [0,0,0,0; 1,1,1,1];
C = [1,0,1,0; 0,1,0,1];
D = bitshift(A,2) + bitshift(B,1) + C;
You can also convert an arbitrary length row vector of zeros and ones into its decimal equivalent by defining this simple function:
mat2dec = #(x) x*2.^(size(x,2)-1:-1:0)';
This will also work for matrices too. For example
>> M = [0 0 1; 0 1 1; 0 1 0; 1 1 0; 1 1 1; 1 1 0; 1 0 0];
>> dec2bin(mat2dec(M))
ans =
001
011
010
110
111
110
100
In my experience, treating binary numbers as strings obfuscates your code and is not very flexible. For example, try adding two binary "strings" together. You have to use bin2dec every time, so why not just leave the numbers as numbers until you want to display them? You have already run into some of the issues caused by strings of different lengths too. You will be amazed how one simple change can break everything when treating numbers as strings. The worst part is that an algorithm may work great for one set of data and not for another. If all I test with is two-bit binary numbers and a three-bit number somehow sneaks its way in, I may not see an error, but my results will be inexplicably incorrect. I realize that this is a very subjective issue, and I think that I definitely stand in the minority on StackOverflow, so take it for what it's worth.
It depends how you want the output formatted. You could apply bitshift to the numerical values and convert to binary:
>> b = dec2bin(bitshift(A,1)+B)
b =
11
00
01
10
For a general matrix Digits:
>> Digits
Digits =
1 0 0 0
0 1 0 0
1 0 1 1
1 1 0 0
1 0 0 0
1 0 1 1
1 1 0 0
1 0 1 0
0 1 1 1
0 1 1 1
>> Ddec = D*(2.^(size(D,2)-1:-1:0))'; % dot product
>> dec2bin(Ddec)
ans =
1000
0100
1011
1100
1000
1011
1100
1010
0111
0111
Another way to write that is dec2bin(sum(D .* repmat(2.^(size(D,2)-1:-1:0),size(D,1),1),2)).
For your larger problem, with 10 large matrixes (say M1, M2, ..., M10), you can build the starting Digits matrix by:
Digits = [M1(:) M2(:) M3(:) M4(:) M5(:) M6(:) M7(:) M8(:) M9(:) M10(:)];
If that is reverse the order of the digits, just do Digits = fliplr(Digits);.
If you would rather not reshape anything you can compute the matrix decimal values from the matrices of digits as follows:
M = cat(3,A,B,C);
Ddec = sum(bsxfun(#times,M,permute(2.^(size(M,3)-1:-1:0),[1 3 2])),3)
I see some quite extensive answers so perhaps this is thinking too simple, but how about just this assuming you have vectors of ones and zeros representing your binary numbers:
A = [1,0,0,1];
B = [1,0,1,0];
C = 10*A + B
This should give you the numbers you want, you may want to add leading zeros. Of course this method can easily be expanded to append multiple matrices, you just need to make sure there is a factor (base) 10 between them before adding.

Matlab: command to check for active bit in binary numbers?

This is how I do it with arrays where binaries are stored
>> hhh=[1 0 1 0 1 0 0; 0 0 1 0 0 0 0; 1 0 1 0 0 0 0; 0 0 0 1 1 0 1]; find(hhh(:,1)==1)
ans =
1
3
and now I am trying to understand how to do it with binary numbers
>> hhhh=[1010100; 0010000; 1010000; 0001101]; find(hhhh(:,1)==1)
ans =
Empty matrix: 0-by-1
where the hack to break up all binaries back into arrays can work (ismember('101010','1') and then prepending with zeros) but I feel there is probably some better alternative so
By which command to check whether Nth bit active in binary number?
P.s. Harder puzzle: is there a type-agnostic solution that would work with both binaries and DEC?
String Input
If you have a string input, you can get away with testing for char equality:
find(hhh(:, 1) == '1')
for string arrays (i.e char matrices), you can extract both outputs of find (rows and columns) to be able to determine which active bit corresponds to which string:
[r, c] = find(hhh == '1');
Numeric Input
For numeric inputs, you can use bitget to get the binary representation. From there, it's very similar to the solution for string inputs:
B = bsxfun(#bitget, hhh, size(hhh, 1):-1:1);
[r, c] = find(B);
Note that find searches for non-zero elements, so there's no need to write find(B == 1) explicitly.
Combined Solution
If the solution for the "harder puzzle" is what you're after, you can determine the type of the input first, and handle it accordingly:
if ischar(hhh)
%// Apply solution to string array
%//...
else if isnumeric(hhh)
%// Apply solution to numeric input
%// ...
else
%// This type is unsupported
assert('Matrix is of unsupported type')
end
Repeating my comment in form of an answer:
There's no need to work with the string/array-like representation of the bits in this case.
You can use bitget right on the output of find(mlf). Like:
filled = find(mlf);
filled_and_bit2 = filled(logical(bitget(filled,2)));
You should store your binary number as a string matrix:
hhhh=['1010100'; '0010000'; '1010000'; '0001101'];
Then you can do
find(bin2dec(hhhh) >= bin2dec('1000000'))
returns:
ans =
1
3
or you could use the less intuitive (but probably faster)
find(hhhh(:,1)-'0') %// Or find(hhhh(:,1)=='1') as EitanT points out
to get the same result.
This is not a direct answer to the question but related -- good point by Sebastian in a comment! So suppose that the binaries are indices. Now instead of playing with dec2bin something like
>> hhh=dec2bin(find(mlf));B=bsxfun(#bitget, hhh, 8:-1:1);find(B)
Error using bsxfun
Non-singleton dimensions of the two input arrays must match each other.
we can directly address the indices like
>> filled = find(mlf);
filled_and_bit2 = bitget(filled,1);
filled(logical(filled_and_bit2))
ans =
1
7
where it finds the binaries with the first active bit.
Procedure
Data
>> mlf=sparse([],[],[],2^31,1);
mlf(1)=7;
mlf(4)=10;
mlf(7)=-1;
>> mlf
mlf =
(1,1) 7
(4,1) 10
(7,1) -1
>> find(mlf)
ans =
1
4
7
Interpret the index numbers as binary
(1,1) -----> 000001
(4,1) -----> 000100
(7,1) -----> 000111
Examples
Output 1: find cases where 3th bit is active
4
7
Output: find cases where 1st bit is active
1
7
Output: find cases where 2nd bit is active
4

change dec2bin in matlab to get a logical vector

I'm looking for a quick way to get a variat of dec2bin in Matlab such that it'll return a logical variable vector. For example given a number n=8 the output will be [1,0,0,0].
How can I do that?
The simplest way is to simply explode the binary representation returned by dec2bin (which is already a string!):
dec2bin(n) == '1'
For n = 8 this returns a logical vector
1 0 0 0
This will also work if n is a vector of numbers.
Since string '1' is char(49) and string '0' is char(48) you can use:
bin = dec2bin(dec) - 48;
This will output the result as an array of doubles, since you are performing an arithmetic operation over an array (the string coming from «dec2bin» is considered an array in Matlab)
If you want to convert very high integers to binary, I recommend using this code:
bin = mod(floor(dec.*2.^-(floor(log2(dec)):-1:0)),2);
In order to convert binary vector to decimal:
dec = sum(bin.*2.^((length(bin)-1):-1:0));
Don't use dec2bin, use bitget instead:
bitget(n, fix(log2(n)) + 1:-1:1)
P.S:
If you have an array of numbers and you want its binary representation as matrix of bits, you might want to take a look at this related question.
Example
n = 8
b = bitget(n, fix(log2(n)) + 1:-1:1)
This results in:
b =
1 0 0 0