function s = dec2base(d,base,nmin)
%MATLAB Code Generation Library Function

%   Copyright 1984-2018 The MathWorks, Inc.
%#codegen

narginchk(2,3);
coder.internal.prefer_const(base);
coder.internal.assert((isnumeric(d) || ischar(d)) && allInRange(d), ...
    'MATLAB:dec2base:FirstArg');
coder.internal.assert((isnumeric(base) || ischar(base)) && isscalar(base), ...
    'MATLAB:dec2base:SecondArg');
b = cast(base(1),'like',d);
coder.internal.assert(base(1) == b && b >= 2 && b <= 36, ...
    'MATLAB:dec2base:SecondArg');
if nargin == 3
    coder.internal.prefer_const(nmin);
    coder.internal.assert((isnumeric(nmin) || ischar(nmin)) && ...
        isscalar(nmin) && nmin(1) == floor(nmin(1)) && ...
        nmin(1) >= 0 && nmin(1) <= intmax(coder.internal.indexIntClass), ...
        'MATLAB:dec2base:ThirdArg');
    n = maxlen(d,b,coder.internal.indexInt(nmin));
else
    n = maxlen(d,b,coder.internal.indexInt(1));
end
symbols = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
nrows = coder.internal.indexInt(numel(d));
s = coder.nullcopy(char(zeros(nrows,n)));
for k = 1:nrows
    if ischar(d)
        dk = double(d(k));
    else
        dk = d(k);
    end
    idx = dec2baseScalar(dk,b,n);
    s(k,:) = symbols(idx);
end

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

function p = allInRange(d)
% Note: because we perform integer calculations natively, we can allow
% 64-bit integers that exceed flintmax.
p = ~isfloat(d) || ...
    coder.internal.vAllOrAny('all',d,@inRange,false);

function p = inRange(x)
p = x >= 0 && x <= flintmax(class(x)) && x == floor(x);

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

function idx = dec2baseScalar(d,b,n)
idx = ones(1,n,'like',d);
idx(1,n) = eml_plus(rem(d,b),1,class(d),'spill');
while d > 0 && n > 1
    n = n - 1;
    if isfloat(d)
        d = floor(d/b);
    else
        d = eml_rdivide(d,b,class(d),'floor','spill');
    end
    idx(1,n) = eml_plus(rem(d,b),1,class(d),'spill');
end

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

function n = maxlen(d,b,nmin)
coder.internal.prefer_const(b,nmin);
type = coder.internal.scalarEg(d,d); % char d --> double.
if coder.internal.isConst(b)
    nmax = coder.const(maxLengthForClass(type,b));
    if coder.internal.isConstTrue(nmin >= nmax)
        % A sufficiently large nmin should result in fixed-size output.
        n = nmin;
        return
    end
else
    TWO = cast(2,'like',type);
    nmax = coder.const(maxLengthForClass(type,TWO));
end
maxd = max(d);
bn = cast(b,'like',type);
n = coder.internal.indexInt(1);
while bn < maxd
    bn = bn*b;
    n = n + 1;
end
if bn == maxd
    n = n + 1;
end
n = eml_max(eml_min(n,nmax),nmin);

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

function n = maxLengthForClass(d,b)
coder.internal.prefer_const(d,b);
if isinteger(d)
    dmax = double(intmax(class(d)));
elseif isfloat(d)
    dmax = double(flintmax(class(d)));
else
    dmax = flintmax;
end
db = double(b);
dn = round(log2(dmax + 1)/log2(db));
while db^dn <= dmax
    dn = dn + 1;
end
n = coder.internal.indexInt(dn);

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