bit level operation in Matlab - matlab

How can we do this bit level operation in Matlab:
int instructionWord;
a = (instructionWord >>> 21) & 0x1F;
The code right shifts the instructionWord by 21 and obtains the least 5 bits. How can this be equivalently done in Matlab?

Given that your input value is an integer, you could do the following:
a = mod( floor(instructionWord/2^21), 32)
Another more bit-like solution would be:
a = bitand( bitshift(instructionWord, -21), hex2dec('1F'))
The last method will throw an error if you feed it anything else than intergers.
By the way, your variable instructionWord is declared like a signed integer. But if it is an instruction word or something like that, an unsigned integer would make more sense. The expressions above expect that your input is only positive. If not, it will require a bit more code to model the >>> (logical right-shift) in matlab.

see the bitshift page:
Code
a = intmax('uint8');
s1 = 'Initial uint8 value %5d is %08s in binary\n';
s2 = 'Shifted uint8 value %5d is %08s in binary\n';
fprintf(s1,a,dec2bin(a))
for i = 1:8
a = bitshift(a,1);
fprintf(s2,a,dec2bin(a))
end
Output
Initial uint8 value 255 is 11111111 in binary
Shifted uint8 value 254 is 11111110 in binary
Shifted uint8 value 252 is 11111100 in binary
Shifted uint8 value 248 is 11111000 in binary
Shifted uint8 value 240 is 11110000 in binary
Shifted uint8 value 224 is 11100000 in binary
Shifted uint8 value 192 is 11000000 in binary
Shifted uint8 value 128 is 10000000 in binary
Shifted uint8 value 0 is 00000000 in binary
EDIT
see bitget page on how to extract a specific bit value.

a = rem( bitshift( instructionWord, -21) , 2^5)
bitshift does the shifting of bits; and rem find the remainder from division by 32 giving last 5 bits' value.

Related

How to disable Matlab Integer Overflow saturation to get signed wraparound

I want to test a piece of function and from 127, it is normal for me that 127+1 = -128. But for Matlab, it saturates my value even though it is a desired behavior on my code.
There are explanations to disable this option on Simulink but what about for a script? I don't know how to disable this feature.
Overflow is not part of Matlab hypotheses.
You need to implement this behaviour in your script using the modulo function (mod).
For example:
>> a=127; mod(a+128,256)-128
ans =
127
>> a=128; mod(a+128,256)-128
ans =
-128
Since you use 127 and -128 as the examples, I assume you are working with int8 variable types. To get the modulo behavior you want, you could use a simple C mex routine to do the arithmetic (since your C compiler will in all likelihood optimize this overflow condition away as simple modulo behavior), or in m-code you can convert to a larger type and do the arithmetic yourself (assumes your machine uses 2's complement storage for integer types). E.g.,
a8 = int8(127); % sample data
b8 = int8(1); % sample data
a16 = int16(a8); % convert to larger type
b16 = int16(b8); % convert to larger type
c16 = a16 + b16 % do the addition in larger type
c16 = int16
128
c8s = typecast(c16,'int8') % typecast back to int8 (assume 2's complement storage)
c8s = 1x2
-128 0
c8 = c8s(1) % pick either c8s(1) or c8s(2) depending on endian of your machine
c8 = int8
-128
If you are working with arrays of numbers instead of scalars, then you could put this in a loop or vectorize the last line as either c8s(1:2:end) or c8s(2:2:end)
You may use fi object from Fixed-Point toolbox and set OverflowAction to Wrap.
Using fi for applying int8 type that overflows, is a bit of an overkill, but possible.
Example:
x = fi(127, true, 8, 0, 'OverflowAction', 'Wrap', 'SumMode', 'SpecifyPrecision', 'SumWordLength', 8, 'SumFractionLength', 0);
x + 1
Output:
ans =
-128
DataTypeMode: Fixed-point: binary point scaling
Signedness: Signed
WordLength: 8
FractionLength: 0
RoundingMethod: Nearest
OverflowAction: Wrap
ProductMode: FullPrecision
SumMode: SpecifyPrecision
SumWordLength: 8
SumFractionLength: 0
CastBeforeSum: true
If you really want to use the int8 overflow and not simulate it with the mod function, you can use the typecast function.
First, you need to convert your variable into an int (otherwise it is by default a double in Matlab). Then you cast it to an int8 and you keep only the first byte:
>> a=127; getfield(typecast(int64(a),'int8'),{1})
ans =
int8
127
>> a=128; getfield(typecast(int64(a),'int8'),{1})
ans =
int8
-128

How to use bitset function in MATLAB to modify multiple bits simultaneously

>> a = 255
a =
255
>> bitset(a,1,0)
ans =
254
here the first bit is set to 0 so we get 11111110 equivalent to 254
>> bitset(a,[1,2],0)
ans =
254 253
here the 1st bit and 2nd bit are being set to 0 seperately. Hence we get
11111110 equivalent to 254
11111101 equivalent to 253
how to get 11111100 equivalent to 252?
Apply bitset twice:
bitset(bitset(a, 1, 0), 2, 0)
The order of application should not matter.
Alternatively, you can use the fact that bitset is an equivalent to applying the correct sequence of bitand, bitor and bitcmp operations.
Since you are interested in turning off multiple bits, you can do
bitand(bitset(a, 1, 0), bitset(a, 2, 0))
Here's a one-liner:
a = 255;
bits = [1,2];
bitand(a,bitcmp(sum(2.^(bits-1)),'uint32'))
Taken apart:
b = sum(2.^(bits-1))
computes the integer with the given bits set. Note that bits must not contain duplicate elements. Use unique to enforce this: bits = unique(bits).
c = bitcmp(b,'uint32')
computes the 32-bit complement of the above. ANDing with the complement resets the given bits.
bitand(a,c)
computes the binary AND of the input number and the integer with the given bits turned off.
Setting bits is easier:
a = 112;
bits = [1,2];
bitor(a,sum(2.^(bits-1)))
Maybe most explicit, easiest to understand, you can convert to a string representing binary and then do the operations there, then convert back.
a = 255
bin_a = flip(dec2bin(a)) % flip to make bigendian
bin_a([1, 2]) = '0'
a = bin2dec(flip(bin_a))
Here is a little recursive function based on the answer from #Mad Physicist that will allow zeroing of any number of bits in data . Thanks for the original info. The recursion is probably dead obvious to most people but it might help somebody out.
function y = zero_nbits(x, n)
y = bitset(x, n, 0)
if n > 1
y = zero_nbits(y, n-1);
end
end

Matlab fast data type conversion 4x1byte to 1x32byte

I am receiving packets of binary data encoding audio samples as 24bit unsigned integers. These need to be converted to 32bit signed (2's complement) integers for output.
However, due to the way the data is chunked, it is possible that a 24bit word be split across a packet boundary. I am therefore buffering each byte as an 8bit unsigned integer, ready to be recast in groups of 3 (+ 1byte of zero-padding) when all packets have been received.
I have written the following function to do this, where input is a 1x3 array of type uint8:
% This function takes 3 8-bit decimal values as input and converts them to
% a single, signed, 32 bit decimal number.
% NOTE - little endianness is assumed
function output = convert24bitTo32bit(input)
sign = bitget(input(3), 8); % get sign bit
bytes(3) = bitset(input(3), 8, 0); % zero sign bit
value = typecast([bytes, uint8(0)], 'int32') - logical(sign)*(2^23);
end
An example can be run using the below snippets:
% Test 255: 11111111 00000000 00000000
input = uint8([255 0 0]);
output = convert24bitTo32bit(input);
fprintf('\n In: 255 \t Out: %d', output)
% Test -2: 01111111 11111111 11111111
input = uint8([254 255 255]);
output = convert24bitTo32bit(input);
fprintf('\n In: -2 \t Out: %d', output)
This function does the job, but is the slowest process in my processing by several orders of magnitude.
Is there a more efficient way to achieve the same result? Or a built-in Matlab function that can handle more esoteric data type conversions?
Thanks
I would work as follows:
Fill your uint8 buffer with as many contiguous 3-byte values as you can:
data = uint8([255 0 0 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3]);
Reshape the matrix into a 3xN matrix (note no data copy happens):
data = reshape(data,3,[]);
Add the zero bytes (this is where a copy happens):
data = [data;zeros(1,size(data,2),'uint8')];
Cast the matrix to int32:
data = typecast(data(:),'int32');
You seem to do some additional tweaking with the sign bit. I think that what you need to do there is pad not with a zero byte, but with a 0 or 255 byte, depending on the sign of the third byte. Step 3 then becomes:
sign = bitget(data(3:3:end),8);
sign = uint8(sign*255);
data = [data;sign,'uint8')];
[Note I have not actually run the code above, please let me know if I made a typo somewhere!]

uencode -signal processing matlab

i need to quantize and encode an input signal using matlab so i will use uencode function . The problem is that i am confused about its process , the description says that it quantize and encode the input as integer and then he has displayed an example :
u = -1:0.01:1;
y = uencode(u,3);
plot(u,y,'.')
The output is just integers , can somebody just explain what this integers exactly are ?? and if i need the binary codes of the input u what i must do to get them ?
uencode takes the range of floating point numbers between -1.0 and 1.0, and maps it to the integers from 0 to (2^n)-1.
For example, with n=8, the possible integers are 0 to 255. -1.0 gets mapped to 0, +1.0 gets mapped to 255, and all decimal values in between get mapped to the closest integer.
In the code example you gave, n=3, so it is mapping to the integers 0 to 7. The plot shows horizontal lines because with so few integers available to map to, many floating point values map to the same integer.
To convert a base 10 integer to a base 2 binary string, use the function dec2bin.
>> dec2bin(5)
ans =
101
>> dec2bin(17)
ans =
10001
If you wanting leading zeros, say so that they are always 8 bits long, use the minimum length as a second argument:
>> dec2bin(5, 8)
ans =
00000101

What is the difference between cast() and typecast() commands in Matlab

Executing these commands in matlab workspace
a = 10
b = cast(a,'uint8')
c = typecast(a,'uint8')
while I look for the values of b and c I get
b = 10
c = 0 0 0 0 0 0 36 64
Also whos('b') and whos('c') returns uint8
The answer comes from the documentation of typecast:
typecast is different from the MATLABĀ® cast function in that it does
not alter the input data. typecast always returns the same number of
bytes in the output Y as were in the input X. For example, casting the
16-bit integer 1000 to uint8 with typecast returns the full 16 bits in
two 8-bit segments (3 and 232) thus keeping its original value (3*256
+ 232 = 1000). The cast function, on the other hand, truncates the input value to 255.