function outValue = num2fixpt( OrigValue, FixPtDataType, FixPtScaling, ...
    RndMeth, DoSatur )
%  NUM2FIXPT  Quantize a value using a Fixed-Point Designer representation.
%   Usage:
%     outValue = num2fixpt(OrigValue,FixPtDataType,FixPtScaling,RndMeth,DoSatur);
%   Inputs:
%   OrigValue      real world value represented using floating point doubles.
%   FixPtDataType  fixed point data type specified using fixdt
%   FixPtScaling   if FixPtDataType specifies scaling, such as fixdt(1,8,3),
%                  then FixPtScaling is ignored.
%                  if FixPtDataType has unspecified scaling, such as fixdt(1,8),
%                  then FixPtScaling provides scaling: Slope or [Slope Bias]
%   RndMeth        rounding toward: 'Zero','Nearest','Ceiling', or 'Floor' [default]
%                  if FixPtDataType is FLOAT, then RndMeth ignored.
%   DoSatur        saturate to min or max on overflow: 'on' or 'off' [default]
%                  if FixPtDataType is FLOAT, then DoSatur ignored.
%   Output:
%   outValue       real world value of OrigValue after quantization to specified
%                  data type and scaling.  If overflows occur, even with
%                  saturation on, outValue and OrigValue can be very different.
%
%   Examples:
%
%   num2fixpt( pi, fixdt(1,8,5), [], 'Nearest', 'on' )
%   num2fixpt( 500/3, fixdt(0,8), [1 0], 'Zero', 'off' )
%
%   See also FI, FIXDT, FIXPTBESTPREC, FIXPTBESTEXP

% Copyright 1994-2017 The MathWorks, Inc.

if nargin > 1
    FixPtDataType = convertStringsToChars(FixPtDataType);
end

if nargin > 2
    FixPtScaling = convertStringsToChars(FixPtScaling);
end

if nargin > 3
    RndMeth = convertStringsToChars(RndMeth);
end

if nargin > 4
    DoSatur = convertStringsToChars(DoSatur);
end

if nargin < 2
    DAStudio.error('Simulink:fixedandfloat:numInputArg');
end

if nargin < 3
    % default scaling
    FixPtScaling = [1 0];
end
if nargin < 4
    % default rounding
    aRndMeth = 'Floor';
else
    aRndMeth = RndMeth;
end
if nargin < 5
    % default saturation mode is off
    aDoSatur = 'off';
else
    aDoSatur = DoSatur;
end

% verifying if input is double
if ~(isa(OrigValue,'double'))
    DAStudio.error('Simulink:fixedandfloat:num2fixptNonDoubleVal');
end

dtv = getdatatypespecs( FixPtDataType, FixPtScaling, -1, 0 );

% % check if the FixPtDataType is a known class
% if  ( (isa(FixPtDataType,'Simulink.NumericType')) || ...
%         isnumerictype(FixPtDataType) )
%     targetDT = FixPtDataType;
% elseif isa(FixPtDataType,'char')
%     try
%         targetDT = fixdt(FixPtDataType);
%     catch err
%         error(message('fixed:numerictype:unrecogDTNameStr', FixPtDataType));
%     end
% else
%     DAStudio.error('Simulink:fixedandfloat:unrecogDTClass');
% end

%FXP_DT_FIXPT         = 0;
FXP_DT_SCALED_DOUBLE = 1;
FXP_DT_DOUBLE        = 2;
FXP_DT_SINGLE        = 3;
FXP_DT_BOOLEAN       = 4;


if (dtv(1)== FXP_DT_SINGLE)
    outValue = double(single(OrigValue));
elseif (dtv(1)== FXP_DT_DOUBLE) || (dtv(1)== FXP_DT_SCALED_DOUBLE)
    outValue = double(OrigValue);
elseif (dtv(1)== FXP_DT_BOOLEAN)
   OrigValue_finite = OrigValue;
   OrigValue_finite(isnan(OrigValue_finite)) = 1; 
   outValue = double(boolean(OrigValue_finite));
else
    % it is a fixed point data-type
       
    WordLength = dtv(2);
    Signed = dtv(3) ; 
    FixedExponent = dtv(4);
    SlopeAdjustmentFactor = dtv(5);
    Bias =  dtv(6);
    targetDT = fixdt( Signed, WordLength, SlopeAdjustmentFactor, FixedExponent, Bias );
    
    
    % find saturation mode
    if strcmp(aDoSatur,'on')
        oflMode = 'saturate';
        OrigValue_finite = OrigValue;
        OrigValue_finite(isnan(OrigValue_finite)) = 0;
        OrigValue_finite(OrigValue==Inf) = realmax;
        OrigValue_finite(OrigValue==-Inf) = -realmax;
    else
        oflMode = 'wrap';
        OrigValue_finite = OrigValue;
        OrigValue_finite(~isfinite(OrigValue_finite)) = 0;
    end
    
    % find rounding mode
    switch lower(aRndMeth(1))
        case 'z'
            rMethod = 'fix';
        case 'n'
            rMethod = 'nearest';
        case 'c'
            rMethod = 'ceil';
        otherwise
            rMethod= 'floor';
    end
    
    % construct fimath object
    F = fimath('OverflowMode',oflMode,...
        'RoundMode',rMethod);
    
    % using fi object constructor to get quantized value
    outValue= double( fi(OrigValue_finite,targetDT,F));
end

% LocalWords:  Rnd Meth Satur fixedandfloat unrecog
