function s = dec2hex(d,n)
%MATLAB Code Generation Library Function

%   * If n is supplied, the output will have a minimum of
%     n columns, even if d is empty. If n is not supplied,
%     the output will have at least one column, even if it is empty.
%   * For code generation, double and single inputs for d must be in the
%     range intmin('int64') <= d < 2^64.
%   * The output is generally variable-size in the number of columns.
%     However, it is possible to force a fixed number of columns. To do
%     this, supply the n input as a constant, and make the value large
%     enough. How large depends on the type of d. It requires at least
%         isa(d,'double')  --> n >= 16
%         isa(d,'single')  --> n >= 16
%         isa(d,'half')    --> n >= 8
%         isa(d,'logical') --> n >= 1
%         isa(d,'char')    --> n >= 2
%         isa(d,'int8')    --> n >= 2
%         isa(d,'uint8')   --> n >= 2
%         isa(d,'int16')   --> n >= 4
%         isa(d,'uint16')  --> n >= 4
%         isa(d,'int32')   --> n >= 8
%         isa(d,'uint32')  --> n >= 8
%         isa(d,'int64')   --> n >= 16
%         isa(d,'uint64')  --> n >= 16

%   Copyright 1984-2020 The MathWorks, Inc.

%#codegen

narginchk(1,2);
coder.internal.assert(coder.internal.isBuiltInNumeric(d) || ...
    isa(d,'half') || islogical(d) || ischar(d), ...
    'MATLAB:dec2hex:FirstArgIsInvalid');
coder.internal.assert(isreal(d) && ~coder.internal.anyNonFinite(d), ...
    'MATLAB:dec2hex:FirstArgIsInvalid');
if nargin < 2
    ncols = coder.internal.indexInt(1);
    if ~coder.target('MATLAB') && coder.internal.isConst(d)
        s = coder.const(feval('dec2hex',d));
        return
    end
else
    coder.internal.prefer_const(n);
    if ~coder.target('MATLAB') && ...
            coder.internal.isConst(d) && ...
            coder.internal.isConst(n)
        s = coder.const(feval('dec2hex',d,n));
        return
    end
    eml_invariant((isnumeric(n) || ischar(n)) && isreal(n) && ...
        isscalar(n) && n >= 0 && n == floor(n), ...
        'MATLAB:dec2hex:InvalidWidth');
    ncols = coder.internal.indexInt(n(1));
end
if islogical(d)
    % DEC2HEX and DEC2BIN are the same functions for logical inputs.
    s = dec2bin(d,ncols);
    return
end
if isa(d,'double') || isa(d,'single')
    if isa(d,'single')
        LO = coder.const(single(intmin('int64')));
        HI = coder.const(pow2(single(64)));
    else
        LO = coder.const(double(intmin('int64')));
        HI = coder.const(pow2(64));
    end
    MUST_BE_GE = @(x)ge(x,LO);
    coder.internal.assert( ...
        coder.internal.vAllOrAny('all',d,MUST_BE_GE), ...
        'MATLAB:dec2hex:NegativeValueOutOfRange');
    MUST_BE_LT = @(x)lt(x,HI);
    coder.internal.assert( ...
        coder.internal.vAllOrAny('all',d,MUST_BE_LT), ...
        'Coder:toolbox:FirstArgumentMustBeLessThan','2^64');
end
TWO = coder.internal.indexInt(2);
nbits = eml_lshift(ncols,TWO);
b = dec2bin(d,nbits);
s = binToHex(b);

%--------------------------------------------------------------------------

function s = binToHex(b)
% Convert binary representation to hex form, a char array of values from
% '0123456789ABCDEF'.
TWO = coder.internal.indexInt(2);
nrows = coder.internal.indexInt(size(b,1));
blen = coder.internal.indexInt(size(b,2));
nCompleteNibbles = eml_rshift(blen,TWO);
srem = blen - eml_lshift(nCompleteNibbles,TWO);
if srem == 0
    slen = nCompleteNibbles;
    s = coder.nullcopy(char(zeros(nrows,slen)));
    for i = 1:nrows
        for j = 0:slen-1
            k = eml_lshift(j,TWO);
            s(i,j + 1) = bin4ToHex( ...
                b(i,k + 1),b(i,k + 2),b(i,k + 3),b(i,k + 4));
        end
    end
else
    slen = nCompleteNibbles + 1;
    s = coder.nullcopy(char(zeros(nrows,slen)));
    % Convert the most significant bits.
    for i = 1:nrows
        if srem == 1
            s(i,1) = bin4ToHex('0','0','0',b(i,1));
        elseif srem == 2
            s(i,1) = bin4ToHex('0','0',b(i,1),b(i,2));
        else % srem == 3
            s(i,1) = bin4ToHex('0',b(i,1),b(i,2),b(i,3));
        end
        for j = 0:nCompleteNibbles - 1
            k = srem + eml_lshift(j,TWO);
            s(i,j + 2) = bin4ToHex( ...
                b(i,k + 1),b(i,k + 2),b(i,k + 3),b(i,k + 4));
        end
    end
end

%--------------------------------------------------------------------------

function h = bin4ToHex(b1,b2,b3,b4)
% Converts 4 bits ('0' or '1', most significant first) to an
% equivalent hexidecimal character.
coder.inline('always');
narginchk(1,4);
if b4 == '1'
    v = uint8(1);
else
    v = uint8(0);
end
if b3 == '1'
    v = eml_plus(v,uint8(2),'uint8','spill');
end
if b2 == '1'
    v = eml_plus(v,uint8(4),'uint8','spill');
end
if b1 == '1'
    v = eml_plus(v,uint8(8),'uint8','spill');
end
if v > uint8(9)
    h = char(eml_plus(v,uint8(55),'uint8','spill'));
else
    h = char(eml_plus(v,uint8(48),'uint8','spill'));
end

%--------------------------------------------------------------------------
