function h = dec2hex(d,numDigits)
%DEC2HEX Convert decimal integer to its hexadecimal representation
%   DEC2HEX(D) returns a character array where each row is the hexadecimal
%   representation of each decimal integer in D. D must contain finite
%   integers.
%
%   DEC2HEX(D,numDigits) produces a character array where each row
%   represents a hexadecimal number with at least numDigits digits.
%
%   Example
%       dec2hex(2748)    returns 'ABC'.
%       dec2hex(251)     returns 'FB'
%       dec2hex(-5)      returns 'FB'
%       dec2hex(2748, 8) returns '00000ABC'
%
%   See also HEX2DEC, HEX2NUM, DEC2BIN, DEC2BASE, FLINTMAX.

%   Copyright 1984-2020 The MathWorks, Inc.

narginchk(1,2);

if ~isreal(d)
    error(message('MATLAB:dec2hex:FirstArgIsInvalid'))
elseif issparse(d)
    error(message('MATLAB:dec2hex:SparseNotSupported'))
end

if isempty(d)
    h = '';
    return;
end

d = d(:); % Make sure d is a column vector.

if any((d~=fix(d) | ~isfinite(d)))
    error(message('MATLAB:dec2hex:FirstArgIsInvalid'))
end

if nargin==1
    numDigits = 1;
elseif ~(isnumeric(numDigits) && isscalar(numDigits) && numDigits>=0 && ...
         isfinite(numDigits) && isreal(numDigits) && numDigits == fix(numDigits)) && ...
       ~ischar(numDigits)
    error(message('MATLAB:dec2hex:InvalidWidth'));
elseif issparse(numDigits)
    error(message('MATLAB:dec2hex:SparseNotSupported'))
end

rowWithNegativeValues = d<0;
if any(rowWithNegativeValues)
    if any(d<intmin('int64'))
        error(message('MATLAB:dec2hex:NegativeValueOutOfRange'))
    end
    
    d = upcastNegatives(d);
end

maxInt = 2^64;

if isfloat(d)
    [~,e] = log2(max(d));
    numOfHexDigitsForValue = ceil(e/4);
else
    numOfHexDigitsForValue = getNumberOfHexDigits(max(d), maxInt);
end

if any(rowWithNegativeValues)
    widerThanNeeded = numDigits>numOfHexDigitsForValue;
end
numDigits = max(numDigits,numOfHexDigitsForValue);
numDigitsArray = numDigits;

numberOfRows = numel(d);
if numberOfRows>1
    numDigitsArray = numDigits*ones(numberOfRows,1);
end

% For small enough numbers, we can do this the fast way.
if all(d < maxInt)
    h = sprintf('%0*X',[numDigitsArray,d]');
else
    if any(d>=2^96)
        error(message('MATLAB:dec2hex:ValueOutOfRange'))
    end

    %Division acts differently for integers
    bits32 = 2^32;
    d = double(d);
    d1 = floor(d/bits32);
    d2 = rem(d,bits32);
    h = sprintf('%0*X%08X',[numDigitsArray-8,d1,d2]');
end

h = reshape(h, numDigits, numberOfRows)';

if any(rowWithNegativeValues) && widerThanNeeded
    for i = find(rowWithNegativeValues')
        h(i,1:regexp(h(i,:),'^0*','end')) = 'F';
    end
end

end


function minDigitsForGivenValue = getNumberOfHexDigits(biggestDec, maxInt)
    
    if biggestDec > maxInt
        [~,powersOfTwo] = log2(double(biggestDec));
        minDigitsForGivenValue = ceil(powersOfTwo/4);
    elseif double(biggestDec) + eps(double(biggestDec)) > maxInt
        minDigitsForGivenValue = 16;
    else
        biggestDec = double(biggestDec);
        minDigitsForGivenValue = 0;
        while (biggestDec >= 1)
            biggestDec = biggestDec / 16; 
            minDigitsForGivenValue = minDigitsForGivenValue+1; 
        end 
    end
    
end
