function yfi = eml_reinterpretcast(xfi, ydt)
%REINTERPRETCAST Fixed-point reinterpretcast function for MATLAB Code Generation
%
%   REINTERPRETCAST(A,T) will cast fi object A to the numerictype of T; A
%   must be of datatype fixed

% $INCLUDE(DOC) toolbox/eml/lib/fixedpoint/@embedded/@fi/eml_reinterpretcast.m $
% Copyright 2007-2016 The MathWorks, Inc.
%#codegen

% This function accepts mxArray input argument
eml_allow_mx_inputs;   

if eml_ambiguous_types
    yfi = coder.ignoreConst(zeros(size(xfi)));
    return;
end

eml_invariant(nargin == 2, 'fixed:coder:incorrectNumberOfInputs');
eml_invariant(isscaledtype(xfi),  'fixed:coder:reinterpretcastFirstInputInvalidDType');
eml_invariant(isnumerictype(ydt), 'fixed:coder:reinterpretcastSecondInputNotNumerictype');

xdt = numerictype(xfi);
eml_invariant((xdt.wordlength == ydt.wordlength), ...
    'fixed:coder:reinterpretcastWordLengthMismatch');

fx = fimath(xfi);

if isfixed(xdt) && isfixed(ydt)
    
    if (ydt.Signed == xdt.Signed)
        
        yfi = eml_reinterpret(xfi,ydt,fx);
        
    else
        
        % Signedness mismatch
        % Emulated types will not be handled properly with a raw reinterpretation
        % Example
        %   Conceptual behavior
        %      x   fixdt(1,3,0)  SI bits      101   RWV =   -3.0
        %      y   fixdt(0,3,0)  SI bits      101   RWV =   +5.0
        %
        %   Behavior when emulated inside 8 bit container with a RAW re-interp
        %
        %      x   fixdt(1,3,0)  SI bits 11111101   RWV =   -3.0
        %      y   fixdt(0,3,0)  SI bits 11111101   RWV = +253.0   Error
        %
        %   The emulation bits must be actively changed to get
        %   the output that agrees with the conceptual behavior of 3 bit type
        %
        %      x   fixdt(1,3,0)  SI bits 11111101   RWV =   -3.0
        %      y   fixdt(0,3,0)  SI bits 00000101   RWV =   +5.0   5 emulation bits changed
        %
        xfi_stripped = eml_reinterpret(xfi);
        
        xdt_trivial_scaling = numerictype(xdt.Signed,xdt.WordLength,0);
        xfi_trivial_scaling = eml_dress(xfi_stripped,xdt_trivial_scaling,fx);
        
        ydt_trivial_scaling = numerictype(ydt.Signed,ydt.WordLength,0);
        %
        % Cast that will change the emulation bits as needed
        %
        yfi_trivial_scaling = fi(xfi_trivial_scaling,ydt_trivial_scaling,'OverflowMode','wrap','DataTypeOverride','Off');
        
        yfi = eml_reinterpret(yfi_trivial_scaling,ydt,fx);
        
    end
    
else
    
    yWL = ydt.WordLength;
    xFL = xdt.FractionLength;
    yFL = ydt.FractionLength;
    ydtOut = numerictype(ydt,'DataType','ScaledDouble');
    ydtOutBP = numerictype(ydt.Signed,yWL,yFL,'DataType','ScaledDouble');
    xdtBP = numerictype(xdt.Signed,yWL,xFL,'DataType',xdt.DataType);
    xfiBP = eml_reinterpret(xfi,xdtBP);
    
    N = xFL - yFL;
    yfiOut = double(xfiBP) .* pow2(double(N));
    
    if coder.const(eml_fimathislocal(xfi))
        yfi = eml_cast(yfiOut, ydtOutBP, fx);
        yfi = eml_reinterpret(yfi, ydtOut, fx); % restore local fimath
    else
        yfi = eml_cast(yfiOut,ydtOutBP);
        yfi = eml_reinterpret(yfi, ydtOut); % return fimath-less fi
    end
    
end
