You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

186 lines
6.2 KiB

function y = int2bit(x, N, MSBFirst)
%INT2BIT Convert integers to bits
%
% Y = INT2BIT(X,N) converts each integer element in X to N
% column-wise bits in Y in 2's complement form, with the first or the
% top-most bit being the MSB (most significant bit). X can be a
% scalar, vector, matrix or an array with 3 dimensions. Y has same
% dimensions as X, except that the number of rows in Y are N times
% the number of rows in X. The datatype of X can be any of the
% built-in numeric types. When the datatype of X is -
% - a floating-point type, Y is of the same datatype.
% - a built-in unsigned integer type, datatype of Y is uint8.
% - a built-in signed integer type, datatype of Y is int8.
% - double, N must be no larger than 53.
% - single, N must be no larger than 24.
% When N is less than the minimum number of bits required to
% represent values in X i.e. N < ceil(log2(max(X)+1)), the least
% significant N bits are returned in Y.
%
% Y = INT2BIT(X,N,MSBFIRST) specifies MSB orientation in MSBFIRST.
% When MSBFIRST is true, the first bit in each set of N column-wise
% bits in Y is the MSB; when MSBFIRST is false, the first bit in each
% set of N column-wise bits in Y is the LSB (least significant bit).
%
% Examples:
%
% A1 = [12 5];
% N1 = 4;
% B1 = int2bit(A1, N1);
%
% A2 = int8([32 6 104; 120 66 9]);
% N2 = 8;
% msbFirst = false;
% B2 = int2bit(A2, N2, msbFirst);
%
% A3 = randi([0,255], 4, 3, 2, 'uint16');
% N3 = 10;
% B3 = int2bit(A3, N3);
%
% A4 = [153, -103, 103, -128];
% B4 = int2bit(A4, 8); % 153 and -103 represent same bits
% B5 = int2bit(A4, 9); % Use additional bit to have unique bits
%
% See also BIT2INT.
% Copyright 2021-2022 The MathWorks, Inc.
%#codegen
narginchk(2,3);
if nargin == 2
MSBFirst = true;
else
validateattributes(MSBFirst, {'logical','numeric'}, {'scalar','binary'}, '', 'MSBFirst');
end
if isfloat(x)
% Output datatype is same as input's
validateattributes(x, {'numeric'}, {'3d','nonempty','integer'}, '', 'X');
if isa(x, 'double')
maxN = 53;
else
maxN = 24;
end
validateattributes(N, {'numeric'}, {'scalar','positive','integer','<=',maxN}, '', 'N');
useN = N;
yType = x(1);
isInputFloat = true;
else
% Output datatype is uint8 or int8
validateattributes(x, {'numeric'}, {'3d','nonempty'}, '', 'X');
validateattributes(N, {'numeric'}, {'scalar','positive','integer'}, '', 'N');
intClass = class(x);
integerClasses = {'int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', 'uint64'};
integerNumBits = [8, 8, 16, 16, 32, 32, 64, 64];
maxN = integerNumBits(strcmp(intClass, integerClasses));
useN = min(N, maxN);
if intClass(1) == 'u'
yType = zeros(1, 'uint8');
else
yType = zeros(1, 'int8');
end
isInputFloat = false;
end
ySize = size(x);
ySize(1) = ySize(1) * N;
if coder.target('MATLAB')
if isInputFloat
% Matrix operations are faster, compared to element-wise
% operations, in MATLAB simulation.
if MSBFirst
powOf2 = pow2(cast(-N+1:0, 'like', x));
else
powOf2 = pow2(cast(0:-1:(-N+1), 'like', x));
end
y = reshape(mod(floor(x(:) * powOf2), 2)', ySize);
else
% Use bitget() for built-in integers in sim to avoid
% floating-point operations.
if useN < N
% When input integer value is negative and useN<N, then the
% non-filling MSB bits must be ones rather than zeros.
y1 = x<0;
y = repelem(cast(y1,'like',yType),N,1);
else
y = zeros(ySize,'like',yType);
end
if MSBFirst
for k=1:useN
y(N-k+1:N:end,:,:) = bitget(x, k);
end
else
for k=1:useN
y(k:N:end,:,:) = bitget(x, k);
end
end
end
else
% Vector operations are faster, compared to matrix operations which
% require data reshape, in generated code.
if isa(x, 'single')
% bitget() is not supported for single. So, convert it to int32.
intInput = cast(x, 'int32');
else
% Double, built-in integers
intInput = x;
end
y = int2bitCG(intInput, N, MSBFirst, useN, yType, ySize);
end
end
function y = int2bitCG(intInput, N, MSBFirst, useN, yType, ySize)
% Code generation algorithm
coder.internal.noRuntimeChecksInThisFunction;
coder.inline('always');
if useN == N
y = coder.nullcopy(zeros(ySize, 'like', yType));
elseif useN < N
% When input integer value is negative and useN<N, then the
% non-filling MSB bits must be ones rather than zeros.
y1 = intInput<0;
y = zeros(ySize,'like',yType); % Preallocating
for ipage = 1:size(y1,3)
tmp = cast(y1(:,:,ipage),'like',yType);
y(:,:,ipage) = repelem(tmp,N,1);
end
else
y = zeros(ySize,'like',yType);
end
ONE = coder.internal.indexInt(1);
nIndexInt = coder.internal.indexInt(N);
useNIndexInt = coder.internal.indexInt(useN);
if isa(intInput,'double')
bitgetclass = 'int64';
else
bitgetclass = class(intInput);
end
if MSBFirst
for k=ONE:useNIndexInt
tmp = bitget(intInput, k, bitgetclass);
for i=ONE:numel(tmp)
j = i*nIndexInt - k + ONE; % N-k+1:N:numel(y)
y(j) = tmp(i);
end
end
else
for k=ONE:useNIndexInt
tmp = bitget(intInput, k, bitgetclass);
for i=ONE:numel(tmp)
j = (i - ONE)*nIndexInt + k; % k:N:numel(y)
y(j) = tmp(i);
end
end
end
end