function edges = binPicker(nxInLimits,LowLimit,HighLimit,nBins,RawBinWidth)
%MATLAB Code Generation Library Function

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

coder.internal.prefer_const(nxInLimits,LowLimit,HighLimit,nBins, ...
    RawBinWidth);
coder.internal.prefer_const(nBins);
if nxInLimits > 0
    xScale = max(abs(LowLimit),abs(HighLimit));
    epsxScale = eps(xScale);
    xOne = ones('like',xScale);
    rMax = realmax(class(xOne));
    xRange = HighLimit - LowLimit;
    % Make sure the bin width is not effectively zero.  Otherwise it will
    % never amount to anything, which is what we knew all along.
    RawBinWidth = max(RawBinWidth,epsxScale);
    tinyRange = max(sqrt(epsxScale),realmin(class(xScale)));
    % If the data are not constant, place the bins at "nice" locations
    if xRange > tinyRange
        % Choose the bin width as a "nice" value.
        powOfTen = 10.^floor(log10(RawBinWidth)); % next lower power of 10
        relSize = RawBinWidth/powOfTen; % guaranteed in [1, 10)
        % Automatic rule specified
        if coder.internal.isConstTrue(isempty(nBins))
            if  relSize < 1.5
                binWidth = 1*powOfTen;
            elseif relSize < 2.5
                binWidth = 2*powOfTen;
            elseif relSize < 4
                binWidth = 3*powOfTen;
            elseif relSize < 7.5
                binWidth = 5*powOfTen;
            else
                binWidth = 10*powOfTen;
            end
            % Put the bin edges at multiples of the bin width, covering x.
            % The actual number of bins used may not be exactly equal to
            % the requested rule.
            leftEdge = min(binWidth*floor(LowLimit/binWidth),LowLimit);
            leftEdge = max(leftEdge,-rMax);
            nbinsActual = max(xOne,ceil((HighLimit - leftEdge)/binWidth));
            rightEdge = max(leftEdge + nbinsActual*binWidth,HighLimit);
        else
            % temporarily set a raw binWidth to a nice power of 10.
            % binWidth will be set again to a different value if more than
            % 1 bin.
            binWidth = powOfTen*floor(relSize);
            % Set the left edge at multiples of the raw bin width.
            % Then adjust bin width such that all bins are of the same
            % size and xmax fall into the rightmost bin.
            leftEdge = min(binWidth*floor(LowLimit/binWidth),LowLimit);
            leftEdge = max(leftEdge,-rMax);
            nbinsActual = cast(nBins,'like',xScale); % check
            if nBins > 1
                % binWidth lower bound, xmax on right edge of last bin
                ll = (HighLimit - leftEdge)/nbinsActual;
                % binWidth upper bound, xmax on left edge of last bin
                ul = (HighLimit - leftEdge)/(nbinsActual - 1);
                FL10 = floor(log10(ul - ll));
                P10 = 10^FL10;
                % binWidth-ll < p10 <= ul-ll; thus, binWidth < ul
                binWidth = P10*ceil(ll/P10);
            end
            rightEdge = max(leftEdge + nbinsActual*binWidth,HighLimit);
        end
        rightEdge = min(rightEdge,rMax);
    else % the data are nearly constant
        % For automatic rules, use a single bin.
        if coder.internal.isConstTrue(isempty(nBins))
            nbinsActual = xOne;
        else
            nbinsActual = cast(nBins,'like',xScale);
        end
        % Create something simple that covers the data.
        binRange = max(1,ceil(nbinsActual*eps(xScale)));
        leftEdge = floor(2*(LowLimit - binRange/4))/2;
        rightEdge = ceil(2*(HighLimit + binRange/4))/2;
        binWidth = (rightEdge - leftEdge)/nbinsActual;
    end
    if isfinite(binWidth)
        % edges = [leftEdge leftEdge+(1:nbinsActual-1).*binWidth rightEdge];
        edges = zeros(1,nbinsActual + 1,'like',LowLimit);
        edges(1) = leftEdge;
        for dk = 1:nbinsActual-1
            edges(dk + 1) = leftEdge + dk*binWidth;
        end
        edges(end) = rightEdge;
    else
        edges = linspace(leftEdge,rightEdge,nbinsActual + 1);
    end
elseif nBins >= 2
    edges = zeros(1,nBins + 1,'like',LowLimit);
    for k = 0:nBins
        edges(k + 1) = k;
    end
else
    edges = cast([0,1],'like',LowLimit);
end
