function [a,b] = polyder(u,v)
%MATLAB Code Generation Library Function

%   Limitations:
%   * The output may contain fewer NaNs than the MATLAB output, but if the
%     input contains a NaN, there will still be at least one NaN in the
%     output.

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

narginchk(1,Inf);
eml_invariant(isfloat(u), ...
    'Coder:toolbox:unsupportedClass','polyder',class(u));
if nargin == 2
    eml_invariant(isfloat(v), ...
        'Coder:toolbox:unsupportedClass','polyder',class(v));
end
ONE = coder.internal.indexInt(1);
if nargin < 2 % a = polyder(u)
    a = trim_leading_zeros(u,true);
    n = coder.internal.indexInt(numel(a));
    for k = ONE:n-1
        a(k) = a(k)*double(n - (k - ONE));
    end
    if ~isempty(u) && ~isfinite(u(end))
        % Guarantee that NaN in ==> NaN out.
        a(end) = coder.internal.nan(class(a));
    end
    b = ones('like',a);
else
    ut = trim_leading_zeros(u,false);
    vt = trim_leading_zeros(v,false);
    a1 = conv(polyder(ut),vt);
    a2 = conv(ut,polyder(vt));
    na1 = coder.internal.indexInt(numel(a1));
    na2 = coder.internal.indexInt(numel(a2));
    % Normally na1 == na2, but we can get different lengths when one input
    % is scalar or empty.
    if na1 >= na2
        offset = na1 - na2;
        for k = offset+1:na1
            if nargout == 2
                a1(k) = a1(k) - a2(k - offset);
            else
                a1(k) = a1(k) + a2(k - offset);
            end
        end
        a = trim_leading_zeros(a1,false);
    else % if na1 < na2
        offset = na2 - na1;
        if nargout == 2
            for k = 1:offset
                a2(k) = -a2(k);
            end
            for k = offset+1:na2
                a2(k) = a1(k - offset) - a2(k);
            end
        else
            for k = offset+1:na2
                a2(k) = a1(k - offset) + a2(k);
            end
        end
        a = trim_leading_zeros(a2,false);
    end
    b = trim_leading_zeros(conv(vt,vt),false);
end

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

function y = trim_leading_zeros(x,ignoreLast)
% 1. Trims leading zeros from an input vector x.
% 2. Always returns a row vector.
% 3. Always returns at least a scalar 0, never empty.
% 4. If eml_option('VariableSizing') is false, the function will check
%    for leading zeros. If none are found, a fixed-size result is returned,
%    otherwise an error is issued.
% 5. To delete the trailing element of x, pass in true for the second
%    argument.
coder.internal.prefer_const(ignoreLast);
ONE = coder.internal.indexInt(1);
nx = coder.internal.indexInt(numel(x));
if ignoreLast
    if nx < 2
        nymax = ONE;
    else
        nymax = nx - ONE;
    end
else
    if nx < 1
        nymax = ONE;
    else
        nymax = nx;
    end
end
y = coder.nullcopy(zeros(1,nymax,'like',x));
if isempty(x) || (ignoreLast && isscalar(x))
    y(1) = 0;
else
    % Count leading zeros.
    nlead0 = coder.internal.indexInt(0);
    for k = 1:nymax - 1
        if x(k) == 0
            nlead0 = nlead0 + ONE;
        else
            break
        end
    end
    if eml_option('VariableSizing')
        ny = nymax - nlead0;
        assert(ny <= nymax); %<HINT>
        y = coder.nullcopy(zeros(1,ny,'like',x));
        for k = 1:ny
            y(k) = x(k + nlead0);
        end
    else
        eml_invariant(nlead0 == 0, ...
            'Coder:toolbox:PolyderNeedsVariableSizing');
        for k = 1:nymax
            y(k) = x(k);
        end
    end
end

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