function [N,D] = rat(x,tol)
%MATLAB Code Generation Library Function

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

narginchk(1,2);
nargoutchk(2,2);
coder.internal.assert(isfloat(x), ...
    'Coder:toolbox:unsupportedClass',mfilename,class(x));
if nargin < 2
    tol = defaultTolerance(x);
end
coder.internal.assert(isscalar(tol) && isfloat(tol) && tol(1) >= 0, ...
    'Coder:toolbox:InvalidTolInput');
if isreal(x)
    [N,D] = coder.internal.applyScalarFunction('rat',zeros('like',x), ...
        @scalarRat,x,tol(1));
elseif norm(imag(x),1) <= tol*norm(real(x),1)
    [NR,D] = rat(real(x),tol);
    N = complex(NR);
else
    [NR,DR] = rat(real(x),tol(1));
    [NI,DI] = rat(imag(x),tol(1));
    D = lcm(DR,DI);
    N = complex(D./DR.*NR,D./DI.*NI);
end

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

function [N,D] = scalarRat(x,tol)
xin = x;
tau = eml_max(cast(tol,'like',x),eps(x));
ZERO = zeros('like',x);
ONE = ones('like',x);
if ~isfinite(x) % Special case for inf, -inf, NaN
    if ~isnan(x)
        if x < 0
            N = -ONE;
        else
            N = ONE;
        end
    else
        N = ZERO;
    end
    D = ZERO;
else
    n = ONE; % n(k)
    d = ZERO; % d(k)
    nlast = ZERO; % n(k - 1)
    dlast = ONE; % d(k - 1);
    stop = false;
    while ~stop
        rndx = round(x);
        if ~isinf(x)
            x = x - rndx;
            tmp = nlast;
            nlast = n;
            n = n*rndx + tmp;
            tmp = dlast;
            dlast = d;
            d = d*rndx + tmp;
        else % Special case for +/- inf
            nlast = n;
            dlast = d;
            n = x;
            d = ZERO;
        end
        if (x == 0) || (abs(n/d - xin) <= tau)
            stop = true;
        else
            x = 1/x;
        end
    end
    N = n/sign(d);
    D = abs(d);
end

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

function tol = defaultTolerance(x)
% tol = 1.e-6*norm(x(isfinite(x)),1);
tol = coder.internal.reduceToScalar(x,@fn,zeros('like',x));
tol = tol*1e-6;

function s = fn(s,xk)
if isfinite(xk)
    s = s + abs(xk);
end

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