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
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
|