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