function I = eye(varargin)
%MATLAB Code Generation Library Function

%   Limitations:
%   1. Does not support dispatching to a static EYE method of a user-defined
%   class, i.e. eye(m,n,'myclass') will not dispatch to myclass.eye(m,n).
%
%   2. Size arguments must be fixed-size

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

coder.internal.allowHalfInputs;
coder.internal.prefer_const(varargin);

% Dispense with the 'like' case as early as possible
if nargin >= 2 && coder.internal.isCharOrScalarString(varargin{end-1}) && strcmpi(varargin{end-1},'like')
    obj = varargin{end};
    eml_invariant(~iscell(obj) && ~ischar(obj), ...
        'Coder:builtins:InputFollowingLikeIsNotANumericArray');
    % Don't call eyeLike for sparse to reuse argument checking code here. Dispatch
    % to sparse code later.
    if ~coder.internal.isBuiltInNumeric(obj) && ~isa(obj,'half') && ~islogical(obj) && ~issparse(obj)
        I = eyeLike(obj, varargin{1:end-2});
        return
    end
end

% Defer the call to narginchk since classes overloading eyeLike can take extra
% arguments
narginchk(0,4);

% Infer the size arguments m and n.
if nargin == 0 || ~isnumeric(varargin{1})
    m = 1;
    n = 1;
    d = coder.internal.indexInt(1);
    otidx = 1;
else
    arg1 = varargin{1};
    if nargin >= 2 && isnumeric(varargin{2})
        [m,n] = coder.internal.checkAndSaturateExpandSize(arg1,varargin{2});
        if m <= n
            d = m;
        else
            d = n;
        end
        otidx = 3;
    elseif coder.internal.isConst(size(arg1)) && isscalar(arg1)
        m = coder.internal.checkAndSaturateExpandSize(arg1);
        n = m;
        d = m;
        otidx = 2;
    else
        eml_invariant(numel(arg1) == 2 && size(arg1,2) == 2, ...
            'MATLAB:eye:unsupportedNd');
        [m,n] = coder.internal.checkAndSaturateExpandSize(arg1(1),arg1(2));
        d = eml_min(m,n);
        otidx = 2;
    end
end

% Determine the output type.
if nargin < otidx
    % No type is specified. Use 'double'.
    ONE = 1;
elseif nargin == otidx
    % Trailing class argument.
    cls = varargin{otidx};
    % Here we will eventually deal with the possibility of
    % eye(m,n,'myclass') should dispatch to myclass.eye(m,n) if such a
    % method exists. However, for now we will just error.
    eml_invariant(coder.internal.isFloatClass(cls) || ...
        coder.internal.isIntegerClass(cls) || ...
        strcmp(cls,'logical') || ...
        strcmp(cls,'half'), ...
        'MATLAB:eye:invalidStringInput');
    ONE = ones(cls);
else
    % The 'like' case
    eml_invariant(strcmpi(varargin{otidx},'like'), ...
        'MATLAB:eye:invalidNumericInput');
    eml_invariant(nargin == otidx+1, ...
        'MATLAB:maxrhs');
    
    obj = varargin{otidx+1};
    ONE = ones('like',obj);
end

if issparse(ONE)
    I = coder.internal.sparse.eyeLike(d,m,n,ones(d,1,'like',ONE));
else
    % Create the matrix and set the diagonal.
    I = zeros(m,n,'like',ONE);
    if d > 0
        for k = 1:d
            I(k,k) = ONE;
        end
    end
end
