function [s,xbar,maxabs,imax] = vvarstd(op,v,omitnan,n,w)
%MATLAB Code Generation Private Function

%   Standard Deviation (op = 'std') or Variance (op = 'var') for a vector V.
%   OMITNAN is true for 'omitnan', false otherwise.
%   N is the number of elements of V to use.
%   W is 0 for the unbiased estimate, 1 for biased, or a
%   weight vector.
%
%   When op = 'std', MAXABS is the maximum absolute deviation from the
%   (possibly weighted) mean, and IMAX is the index where the maximum
%   absolute deviation occurs. These outputs are not supported when op =
%   'var'.

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

coder.internal.prefer_const(op);
ZERO = coder.internal.indexInt(0);
ONE = coder.internal.indexInt(1);
if nargin < 3
    omitnan = false;
else
    coder.internal.prefer_const(omitnan);
end
if nargin < 4
    n = coder.internal.indexInt(length(v));
else
    coder.internal.prefer_const(n);
end
if nargin < 5
    WEIGHTVECTOR = false;
    w = zeros('like',real(v));
else
    WEIGHTVECTOR = ~coder.internal.isConstTrue(isscalar(w));
end
if WEIGHTVECTOR
    vwzero = coder.internal.scalarEg(v,w);
    rzero = real(vwzero);
else
    vwzero = coder.internal.scalarEg(v,v);
    rzero = real(vwzero);
end
OMITNAN = omitnan && isfloat(v);
offset = zeros(length(v),1,coder.internal.indexIntClass);
if OMITNAN
    nnans = ZERO;
    for k = 1:n
        if isnan(v(k)) || (WEIGHTVECTOR && isnan(w(k)))
            nnans = nnans + 1;
            offset(k) = nnans;
        else
            v(k - nnans) = v(k);
            if WEIGHTVECTOR
                w(k - nnans) = w(k);
            end
        end
    end
    assert(nnans >= ZERO); %<HINT>
    assert(nnans <= n); %<HINT>
    nn = n - nnans;
else
    nn = n;
end
if nn == 0
    s = coder.internal.nan('like',rzero);
    xbar = coder.internal.nan('like',vwzero);
    maxabs = rzero;
    imax = ZERO;
elseif nn == 1
    if WEIGHTVECTOR
        xbar = v(1)*w(1);
    else
        xbar = v(1);
    end
    if isfinite(xbar)
        s = rzero;
    else
        s = coder.internal.nan('like',rzero);
    end
    maxabs = rzero;
    imax = ONE;
else
    dim = coder.internal.constNonSingletonDim(v);
    if WEIGHTVECTOR
        vtmp = zeros(length(v),1,'like',vwzero);
        for k = 1:nn
            vtmp(k) = w(k)*v(k);
        end
        wzero = coder.internal.scalarEg(w);
        dimw = coder.internal.constNonSingletonDim(w);
        wsum = combineVectorElements(@plus,w,wzero,dimw,false,nn);
        xbartmp = combineVectorElements(@plus,vtmp,vwzero,dim,false,nn);
        xbar = xbartmp/wsum;
    else
        xbar = combineVectorElements(@plus,v,vwzero,dim,false,nn);
        xbar = xbar/cast(nn,'like',rzero);
    end
    imax = ONE;
    maxabs = rzero;
    if coder.const(strcmpi(op,'var'))
        % Compute the variance
        nargoutchk(0,2); % MAXABS and IMAX outputs are not supported.
        s = rzero;
        for k = 1:nn
            t = real(v(k)) - real(xbar);
            absdiffsq = t*t;
            if ~isreal(v)
                t = imag(v(k)) - imag(xbar);
                absdiffsq = absdiffsq + t*t;
            end
            if WEIGHTVECTOR
                absdiffsq = absdiffsq*(w(k)/wsum);
            end
            s = s + absdiffsq;
        end
        if ~WEIGHTVECTOR
            if w == 1
                s = s/cast(nn,'like',s);
            else
                s = s/cast(nn - 1,'like',s);
            end
        end
    else
        % Compute the standard deviation
        absdiff = coder.nullcopy(zeros(size(v,dim),1,'like',rzero));
        for k = 1:nn
            if WEIGHTVECTOR
                absdiff(k) = sqrt(w(k)/wsum)*abs(v(k) - xbar);
            else
                absdiff(k) = abs(v(k) - xbar);
            end
            if absdiff(k) > maxabs
                maxabs = absdiff(k);
                imax = k;
            end
        end
        s = coder.internal.blas.xnrm2(nn,absdiff,ONE,ONE);
        if ~WEIGHTVECTOR
            if w == 1
                s = s/sqrt(cast(nn,'like',s));
            else
                s = s/sqrt(cast(nn - 1,'like',s));
            end
        end
    end
    if OMITNAN && nargout == 4
        imax = imax + offset(imax);
    end
end
