function cis_out = cordiccexp(theta, niters)
% CORDICCEXP(theta, niters) Compute the CORDIC-based approximation to the complex exponential COS(theta) + jSIN(theta).

% Copyright 2009-2014 The MathWorks, Inc.
%#codegen

coder.allowpcode('plain');
coder.internal.prefer_const(theta);

% Initialize output memory
real_vals_dbl = ones(length(theta(:)), 1);
cplx_vals_dbl = reshape(complex(real_vals_dbl, real_vals_dbl), size(theta));
if isa(theta, 'double')
    cis_out = coder.nullcopy(cplx_vals_dbl);
elseif isa(theta, 'single')
    cis_out = coder.nullcopy(single(cplx_vals_dbl));
elseif isfi(theta) && isfloat(theta)
    % FI Double or Single THETA input
    cis_out = coder.nullcopy(fi(cplx_vals_dbl, numerictype(theta)));
else
    % Fixed-point or integer THETA
    if isfi(theta)
        thetaNT      = numerictype(theta);
        ioWordLength = thetaNT.WordLength;
    
        eml_invariant(ioWordLength > 1, ...
            'fixed:cordic:inputWordLengthNotGTOne');
    else
        % Builtin integer THETA input
        switch class(theta)
          case { 'int8',  'uint8'}
            ioWordLength =  8;
          case {'int16', 'uint16'}
            ioWordLength = 16;
          case {'int32', 'uint32'}
            ioWordLength = 32;
          otherwise
            ioWordLength = 64;
        end
    end
    
    ioFracLength = ioWordLength - 2;
    if isfi(theta)
        ioNT = numerictype(numerictype(1, ioWordLength, ioFracLength),'DataType',thetaNT.DataType);
    else
        ioNT = numerictype(1, ioWordLength, ioFracLength);
    end
    cis_out      = coder.nullcopy(fi(cplx_vals_dbl, ioNT, 'fimath', []));
end

% Generate CORDIC SIN-COS code
if (nargin == 1)
    [sin_out, cos_out] = cordicsincos(theta);
else
    coder.internal.prefer_const(niters);
    [sin_out, cos_out] = cordicsincos(theta, niters);
end

% Copy real SIN-COS values to COMPLEX outputs
for idx = 1:length(sin_out(:))
    cis_out(idx) = complex(cos_out(idx), sin_out(idx));
end

end % function

