function y = rescale(x,varargin)
% MATLAB Code Generation Library function.
%
%RESCALE  Change the scaling of a fixed-point number.
%   B = RESCALE(A, FractionLength)
%   B = RESCALE(A, Slope, Bias)
%   B = RESCALE(A, SlopeAdjustmentFactor, FixedExponent, Bias)
%   B = RESCALE(A, Parameter1,Value1, ...)
%   returns fi object B with the same stored-integer-value as A, but
%   with new scaling applied.  Only scaling parameters are allowed in
%   the parameter/value pairs.
%
%   RESCALE is similar to the FI copy constructor, except
%     (1) The FI constructor preserves the real-world-value, while RESCALE
%     preserves the stored-integer-value.
%     (2) RESCALE does not allow Signed and WordLength properties to be
%     changed.
%
%   Examples:
%
%     A = fi(10, 1, 8, 3);
%     B = rescale(A,1)
%     In this example, A's stored-integer-value is scaled by 2^-3, and 
%     B preserves the stored-integer-value of A, but changes the scaling to 2^-1. 
%     Thus, 
%       A has real-world-value 10 = (stored-integer-value 80)*2^-3
%       B has real-world-value 40 = (stored-integer-value 80)*2^-1

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

% This MATLAB Coder library function allows and can handle mxArray inputs
eml_allow_mx_inputs;  

coder.inline('always');

coder.extrinsic('feature');

% Support Simulink size propagation. Input may be (built-in) double.
narginchk(1,inf);
if eml_ambiguous_types
    y = x;
    return
end

% Give a generic error for non-fi inputs.
coder.internal.assert(isfi(x), ... 
    'Coder:toolbox:unsupportedClass','rescale',class(x));

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

if isscaledtype(x)
    % FI objects with Fixed datatype
    
    nNumerictypeVar = nargin-1;
    % Check to see if x is a fi. If x is not a fi assert. 
    eml_invariant(isfi(x),'fixed:fi:firstInputNotFi');

    t_x    = eml_typeof(x);
    WL     = coder.const(get(t_x, 'WordLength'));
    s      = coder.const(get(t_x, 'Signed'));
    F      = fimath(x);

    T1 = numerictype(numerictype(s, WL,0),'DataType',t_x.DataType);
    % Switch on the number of input arguments.
    switch nNumerictypeVar
      case 1 % rescale(A, fractionlength)
        T = numerictype(numerictype(s,  WL, varargin{1}),'DataType',t_x.DataType);
      case 2 % rescale(A, Slope, Bias) or rescale(A, var1, var2)
             % Find the position of the first char argument, which indicates the
             % start of the parameter/value pairs.
        if ischar(varargin{1})
            T = numerictype(T1, varargin{1}, varargin{2});
        else
            T = numerictype(numerictype(s, WL, varargin{1}, varargin{2}),'DataType',t_x.DataType);        
        end
      case 3 % rescale(A, SlopeAdjustmentFactor, FixedExponent, Bias)
        T = numerictype(numerictype(s, WL, varargin{1}, varargin{2}, varargin{3}),...
            'DataType',t_x.DataType);        
      otherwise
        T = numerictype(T1, varargin{:});
    end
    
    if coder.const(~isequal(T1.Signed,T.Signed))
        eml_invariant(false, 'fixed:fi:rescaleNoSignChange');
    end
    
    if coder.const(~isequal(T1.WordLength,T.WordLength))
        eml_invariant(false, 'fixed:fi:rescaleNoWordLengthChange');
    end
    
    if coder.const(feature('FiRealOnlySlopeBias'))
        eml_invariant((isreal(x) || ~isslopebiasscaled(T)), ...
            'fixed:fi:unsupportedComplexSlopeBias');
    end

    yHasLocalFimath = coder.const(eml_fimathislocal(x));
    if isfixed(x)
        y = eml_fimathislocal(eml_dress(x,T,F),yHasLocalFimath);
    else
        valX = storedInteger(x);
%         yTemp = fi('numerictype',T,'fimath',F,'int',valX);
        yDbl = valX*T.Slope + T.Bias;
        yTemp = eml_cast(yDbl,T,F);
        y = eml_fimathislocal(yTemp,yHasLocalFimath);
    end
    
    %if ~coder.const(eml_fimathislocal(x))
    %    y = eml_fimathislocal(ytemp,false);
    %else
    %    y = ytemp;
    %end
    
elseif isfloat(x)
    % True Double or True Single FI
    y = x;
else
    % FI datatype not supported
    eml_fi_assert_dataTypeNotSupported('RESCALE');
end
