function [e,cnt] = normest(S,tol)
%MATLAB Code Generation Library Function

%   Copyright 2002-2017 The MathWorks, Inc.
%#codegen

coder.columnMajor;
coder.internal.assert(nargin > 0, ...
    'MATLAB:minrhs');
coder.internal.assert(isa(S,'float'), ...
    'Coder:toolbox:unsupportedClass','normest',class(S));
coder.internal.assert(ismatrix(S), ...
    'Coder:toolbox:normest_inputMustBe2D');
if nargin < 2
    tol = 1.e-6;
else
    coder.internal.assert(isa(tol,'float'), ...
        'Coder:toolbox:unsupportedClass','normest',class(tol));
    coder.internal.assert(isreal(tol), ...
        'Coder:toolbox:normest_5', ...
        'IfNotConst','Fail');
end
cnt = 0;
if isempty(S)
    e = zeros('like',real(S));
elseif coder.internal.isConst(isvector(S)) && isvector(S)
    e = norm(S);
else
    ONE = ones(coder.internal.indexIntClass);
    M = cast(size(S,1),coder.internal.indexIntClass);
    N = cast(size(S,2),coder.internal.indexIntClass);
    x = sum_abs_transpose(S);
    e = norm(x);
    if e == 0, return, end
    x = coder.internal.div(x,e);
    e0 = zeros('like',real(S));
    while abs(e-e0) > tol*e
        e0 = e;
        Sx = S*x;
        if is_all_zeros(Sx)
            for k = 1:numel(Sx)
                Sx(k) = rand;
            end        
        end
        x = coder.internal.blas.xgemv('C',M,N,1,S,ONE,size(S,1),Sx,ONE,ONE,0,x,ONE,ONE);
        normx = norm(x);
        e = eml_rdivide(normx,norm(Sx));
        x = coder.internal.div(x,normx);
        cnt = cnt + 1;
    end
end

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

function p = is_all_zeros(x)
% p = ~any(x) without ignoring NaNs.
coder.inline('always');
p = true;
for k = 1:numel(x)
    if x(k) ~= 0
        p = false;
        return
    end
end

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

function x = sum_abs_transpose(S)
% Calculate x = sum(abs(S),1)' efficiently.
coder.inline('always');
x = eml_expand(coder.internal.scalarEg(S),[size(S,2),1]);
for j = 1:size(S,2)
    for i = 1:size(S,1)
        x(j) = x(j) + abs(S(i,j));
    end
end

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