224 lines
7.8 KiB
Matlab
224 lines
7.8 KiB
Matlab
function y = bit2int(x, N, varargin)
|
|
%BIT2INT Convert bits to integers
|
|
%
|
|
% Y = BIT2INT(X,N) converts N column-wise bit elements in X to
|
|
% nonnegative integer values, with the first or the top-most bit
|
|
% being the MSB (most significant bit). X can be a column vector,
|
|
% matrix or an array with 3 dimensions. Number of rows in X must be
|
|
% an integer multiple of N. Y has same dimensions as X, except that
|
|
% the number of rows in Y are N times less than the number of rows in
|
|
% X. The datatype of X can be any of the built-in numeric types or
|
|
% logical. When the datatype of X is -
|
|
% - double or logical, datatype of Y is double.
|
|
% - single, datatype of Y is single.
|
|
% - a built-in integer type, Y has the same datatype as X unless the
|
|
% values in Y cannot be represented in that datatype without loss of
|
|
% data. If values in Y are larger than the intmax of the datatype of
|
|
% X, then Y is of the smallest datatype that can fit the values
|
|
% without loss of data. The datatype of Y has same signedness as that
|
|
% of X.
|
|
% - double or logical, N must be no larger than 53.
|
|
% - single, N must be no larger than 24.
|
|
% - a built-in signed integer type, N must be no larger than 63.
|
|
% - a built-in unsigned integer type, N must be no larger than 64.
|
|
%
|
|
% Y = BIT2INT(X,N,MSBFIRST) specifies MSB orientation in MSBFIRST.
|
|
% When MSBFIRST is true, the first bit in each set of N column-wise
|
|
% bits in X is the MSB; when MSBFIRST is false, the first bit in each
|
|
% set of N column-wise bits in X is the LSB (least significant bit).
|
|
%
|
|
% Y = BIT2INT(___,IsSigned=TF) specifies TF as a logical which can be
|
|
% either true or false to indicate the signed-ness of the integer.
|
|
% Default is false. When TF is true, then the first bit in each block
|
|
% of N bits is considered to be a signed bit and the output may
|
|
% contain negative values. If the datatype of X is any of the
|
|
% unsigned integer types with TF set to true, then the datatype of Y
|
|
% is the smallest signed integer type that can support the number of
|
|
% input bits.
|
|
%
|
|
% Examples:
|
|
%
|
|
% A1 = [1 0 1 0 1 0 1 0]';
|
|
% N1 = 8;
|
|
% B1 = bit2int(A1, N1);
|
|
%
|
|
% A2 = int8([1 1 0; 0 1 1]');
|
|
% N2 = 3;
|
|
% msbFirst = false;
|
|
% B2 = bit2int(A2, N2, msbFirst);
|
|
%
|
|
% A3 = randi([0,1], 32, 2, 2, 'uint8');
|
|
% N3 = 16;
|
|
% B3 = bit2int(A3, N3);
|
|
%
|
|
% A4 = [-110, 103, -103, 99];
|
|
% C4 = int2bit(A4,8);
|
|
% B4 = bit2int(C4,8,IsSigned=true);
|
|
%
|
|
% See also INT2BIT.
|
|
|
|
% Copyright 2021-2022 The MathWorks, Inc.
|
|
|
|
%#codegen
|
|
narginchk(2,5);
|
|
validateattributes(x, {'numeric','logical'}, {'3d','nonempty','binary'}, '', 'X');
|
|
if nargin == 2
|
|
MSBFirst = true;
|
|
IsSigned = false;
|
|
elseif nargin == 3
|
|
% If 3 inputs, then third argument must be MSBFirst option
|
|
IsSigned = false;
|
|
MSBFirst = varargin{1};
|
|
validateattributes(MSBFirst, {'logical','numeric'}, {'scalar','binary'}, '', 'MSBFirst');
|
|
else
|
|
% Then either 4 inputs with name-value is possible or 5 inputs with
|
|
% MSBFirst option and name-value of IsSigned is possible
|
|
if nargin == 4
|
|
signedOption = {varargin{1:2}}; % Codegen does not support cellarray(...). So use curly braces
|
|
MSBFirst = true;
|
|
else % nargin == 5
|
|
MSBFirst = varargin{1};
|
|
signedOption = {varargin{2:3}};
|
|
validateattributes(MSBFirst, {'logical','numeric'}, {'scalar','binary'}, '', 'MSBFirst');
|
|
end
|
|
|
|
defaults = struct("IsSigned",false);
|
|
res = comm.internal.utilities.nvParser(defaults, signedOption{:});
|
|
IsSigned = res.IsSigned;
|
|
validateattributes(IsSigned, {'logical','numeric'}, {'scalar','binary'}, '', 'IsSigned');
|
|
end
|
|
|
|
isSim = comm.internal.utilities.isSim();
|
|
if ~isSim
|
|
coder.internal.prefer_const(N);
|
|
end
|
|
isInputLogical = islogical(x);
|
|
|
|
% When N is equal to the max int supported (for example, N==8 for
|
|
% int8), -2^N calculation gives us -2^N + 1 because first 2^N gets
|
|
% calculated which cannot be fit into its native integer type (for
|
|
% example, int8 for N=8). To handle this corner case, subtract one
|
|
% after calculating negative value.
|
|
subone = false;
|
|
|
|
if isfloat(x) || isInputLogical
|
|
if isa(x, 'single')
|
|
maxN = 24;
|
|
else
|
|
maxN = 53;
|
|
end
|
|
|
|
validateattributes(N, {'numeric'}, {'scalar','positive','integer','<=',maxN}, '', 'N');
|
|
if isInputLogical
|
|
xNew = double(x);
|
|
isInputFloat = false;
|
|
else
|
|
xNew = x;
|
|
isInputFloat = true;
|
|
end
|
|
prototype = xNew(1);
|
|
else
|
|
% built-in integers
|
|
bitClass = class(x);
|
|
if bitClass(1) == 'u'
|
|
maxN = 64;
|
|
else
|
|
maxN = 63;
|
|
end
|
|
validateattributes(N, {'numeric'}, {'scalar','positive','integer','<=',maxN}, '', 'N');
|
|
coder.internal.errorIf(~isSim && ~coder.internal.isConst(N), ...
|
|
'comm:bit2int:NNotConst');
|
|
if bitClass(1) == 'u' && IsSigned
|
|
bitClassMax = intmax(bitClass(2:end));
|
|
else
|
|
bitClassMax = intmax(bitClass);
|
|
end
|
|
|
|
if IsSigned
|
|
c = '';
|
|
else
|
|
c = 'u';
|
|
end
|
|
|
|
if bitClass(1) == 'u' || IsSigned
|
|
if N <= 8
|
|
typeMax = intmax([c 'int8']);
|
|
subone = N==8;
|
|
elseif N <= 16
|
|
typeMax = intmax([c 'int16']);
|
|
subone = N==16;
|
|
elseif N <= 32
|
|
typeMax = intmax([c 'int32']);
|
|
subone = N==32;
|
|
else
|
|
typeMax = intmax([c 'int64']);
|
|
subone = N==64;
|
|
end
|
|
else
|
|
if N <= 7
|
|
typeMax = intmax('int8');
|
|
elseif N <= 15
|
|
typeMax = intmax('int16');
|
|
elseif N <= 31
|
|
typeMax = intmax('int32');
|
|
else
|
|
typeMax = intmax('int64');
|
|
end
|
|
end
|
|
|
|
if bitClassMax > typeMax
|
|
prototype = bitClassMax;
|
|
subone = false;
|
|
else
|
|
prototype = typeMax;
|
|
end
|
|
xNew = x;
|
|
isInputFloat = false;
|
|
end
|
|
useN = cast(N,'like',prototype);
|
|
|
|
if isInputFloat || (isSim && isInputLogical)
|
|
|
|
inSize = size(xNew);
|
|
nIntsPerCol = inSize(1)/double(N);
|
|
coder.internal.errorIf(nIntsPerCol ~= floor(nIntsPerCol), 'comm:bit2int:InvalidInputDims');
|
|
outSize = inSize;
|
|
outSize(1) = nIntsPerCol;
|
|
xMat = reshape(xNew, useN, []);
|
|
if MSBFirst
|
|
powOf2 = pow2(useN-1:-1:0);
|
|
powOf2(1) = (1-2*IsSigned)*powOf2(1);
|
|
else
|
|
powOf2 = pow2(0:useN-1);
|
|
powOf2(end) = (1-2*IsSigned)*powOf2(end);
|
|
end
|
|
|
|
y = reshape(powOf2 * xMat, outSize);
|
|
|
|
else
|
|
|
|
Nidx = coder.internal.indexInt(useN);
|
|
[nRows,nCols,nPages] = size(xNew);
|
|
nIntsPerCol = idivide(nRows, Nidx);
|
|
coder.internal.errorIf(Nidx*nIntsPerCol ~= nRows, ...
|
|
'comm:bit2int:InvalidInputDims');
|
|
|
|
y = coder.nullcopy(zeros(nIntsPerCol, nCols, nPages, 'like', prototype));
|
|
|
|
powOf2 = cast(2, 'like', y) .^ (useN-1:-1:0)';
|
|
powOf2(1) = (1-2*IsSigned)*powOf2(1)-1*subone*IsSigned;
|
|
xTmp = cast(xNew, 'like', y);
|
|
nInts = nIntsPerCol * coder.internal.indexInt(nCols) * coder.internal.indexInt(nPages);
|
|
if MSBFirst
|
|
idx = 1:Nidx;
|
|
else
|
|
idx = Nidx:-1:1;
|
|
end
|
|
for k=1:nInts
|
|
bits = xTmp(Nidx*(k-1) + idx);
|
|
y(k) = sum(bits(:) .* powOf2, 'native');
|
|
end
|
|
end
|
|
|
|
end
|