function c = bitget(a,bit)
% MATLAB Code Generation Library function.
%
% BITGET Get bit.
%    C = BITGET(A,BIT) returns the value of the bit at position BIT of the
%    stored-integer or fi objects A.
%
%    A must be a fixed-point fi object. A may be scalar, vector, matrix, N-D.
%    A may be signed or unsigned.
%
%    BIT must be a numeric scalar, vector, matrix, N-D. All values of BIT must
%    be between 1 and the word length of A, inclusive.
%
% Note: Difference from the MATLAB Toolbox BITGET:
%   When A and B are both non-fi, the MATLAB Toolbox BITGET
%   restricts A to be unsigned (uint8, uint16, uint32, ...).
%   Here we loosen that restriction because the Fixed-Point Designer
%   BITSET accepts the signed case.

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

eml_invariant(nargin == 2, 'fixed:coder:notEnoughInputArguments');

if eml_ambiguous_types
    c = coder.ignoreConst(reshape(zeros(size(a)), size(a)));
    return;
end

coder.internal.prefer_const(bit);
if eml_is_const(bit)
    eml_invariant(~isempty(bit), ...
        'fixed:fi:bitMustBeInteger','BITGET');
end
eml_invariant(isnumeric(bit), ...
    'fixed:fi:indexMustBeNumeric','BITGET');
eml_invariant(isreal(a) && isreal(bit), ...
    'fixed:fi:unsupportedComplexArguments','BITGET');
eml_invariant(coder.internal.scalexpCompatible(a,bit), ...
    'fixed:fi:DimAgree');
eml_invariant(isfi(a) && isfixed(a), ...
    'fixed:coder:fiFcnDTypeErrorFixPtOnly','BITGET');

aWL = a.WordLength;

if eml_is_const(bit)
    eml_invariant(all(bit(:) > 0) && all(bit(:) <= aWL), ...
        'fixed:fi:bitPositionInvalid', ...
            'BIT', 'A', 'BITGET(A,BIT)');
end

Tbit = numerictype(0,1,0);
Fbit = fimath(a);

% First decide the output size
% If a is a fimath-less fi then c is also one.
if ~isscalar(a)
    c1 = eml_cast(zeros(size(a)),Tbit,Fbit);
else
    c1 = eml_cast(zeros(size(bit)),Tbit,Fbit);
end

if coder.const(eml_fimathislocal(a))
    c = c1;
else
    c = eml_fimathislocal(c1,false);
end

if isscalar(c)
    coder.inline('always');
end

for k = 1:numel(c)
    % Here we trust the compiler to optimize invariant cases inside the loop.
    a1   = eml_scalexp_subsref(a,  k);
    bit1 = eml_scalexp_subsref(bit,k);
    
    if (bit1 >= 1) && (bit1 <= aWL)
        % Go from 1-based to 0-based index, using integer index data type
        bit_idx = convertOneBasedBitIndexToZeroBased(bit1);
        c(k) = eml_bitslice(a1, bit_idx, bit_idx);
    else
        % Bit index out of range
        c(k) = eml_cast(0,Tbit,Fbit);
        coder.internal.error('Coder:MATLAB:bitSetGet_BITOutOfRange', ...
                  int32(aWL), class(a1));
    end
end

% -------------------------------------------------------------------------
function bit_idx = convertOneBasedBitIndexToZeroBased(bit1)
coder.internal.prefer_const(bit1);
if eml_is_const(bit1)
    bit_idx = uint8(floor(double(bit1)) - 1);
elseif isinteger(bit1)
    bit_idx = eml_minus(uint8(bit1),uint8(1),'uint8');
elseif isfloat(bit1)
    bit_idx = uint8(floor(bit1) - 1);
elseif isfi(bit1) && isfixed(bit1)
    % Fixed-point bit index value
    if eml_isslopebiasscaled(bit1)
        % Note: slope-bias with FLOOR -> error
        bit_idx = uint8(floor(double(bit1)) - 1);
    elseif isequal(bit1.FractionLength, 0)
        % Already an integer (stored in a FI)
        bit_idx = uint8(storedInteger(bit1) - 1);
    else
        % Arbitrary binary point scaled fixed-point
        bit_idx = uint8(floor(bit1) - 1);
    end
else
    bit_idx = uint8(floor(double(bit1)) - 1);
end
