function [DataType,IsScaledDouble] = fixdt( varargin )
%  FIXDT Create an object describing a fixed-point or floating-point data type
%
%  This data type object can be passed to Simulink blocks that support
%  fixed-point data types.
%
%  Usage 1: Fixed-Point Data Type With Unspecified scaling
%          Scaling would typically be determined by another block parameter.
%
%   FIXDT( Signed, WordLength )
%
%  Usage 2: Fixed-Point Data Type With Binary point scaling
%
%   FIXDT( Signed, WordLength, FractionLength )
%
%  Usage 3: Slope and Bias scaling
%
%   FIXDT( Signed, WordLength, TotalSlope, Bias )
%  or
%   FIXDT( Signed, WordLength, SlopeAdjustmentFactor, FixedExponent, Bias )
%
%  Usage 4: Data Type Name String
%
%   FIXDT( DataTypeNameString )
%  or
%   [DataTypeObject,IsScaledDouble] = FIXDT( DataTypeNameString )
%     
%   The data type name string is the same string that would be displayed on 
%   signal lines in a Simulink model.  The optional setting to display port 
%   data types is found under the Simulink Display menu.
%
%   Examples using standard data types:
%
%      fixdt('double');
%      fixdt('single');
%      fixdt('half');
%      fixdt('uint8');
%      fixdt('uint16');
%      fixdt('uint32');
%      fixdt('int8');
%      fixdt('int16');
%      fixdt('int32');
%      fixdt('boolean');
%
%   Key to fixed-point data type names: 
%
%      Simulink data type names are required to be valid MATLAB 
%      identifiers.  Fixed-point data types are encoded using 
%      the following rules.
%          
%      Container
%
%        'ufix#'  unsigned with # bits  Ex. ufix3   is unsigned   3 bits
%        'sfix#'  signed   with # bits  Ex. sfix128 is signed   128 bits
%        'flts#'  scaled double data type override of sfix#
%        'fltu#'  scaled double data type override of ufix#
%
%      Number encoding
%
%        'n'      minus sign,           Ex. 'n31' equals -31
%        'p'      decimal point         Ex. '1p5' equals 1.5
%        'e'      power of 10 exponent  Ex. '125e18' equals 125*(10^(18))
%
%      Scaling Terms from the fixed-point scaling equation
% 
%           RealWorldValue = S * StoredInteger + B
%        'S'      TotalSlope              default value is 1
%        'B'      Bias                    default value is 0
%
%         or if S is not given, 
%           RealWorldValue = F * 2^E * StoredInteger + B
%
%        'E'      FixedExponent           default value is 0
%        'F'      SlopeAdjustmentFactor   default value is 1
%
%     Examples:
%
%     % using integers with non-standard number of bits
%
%        fixdt('ufix1');       % Unsigned  1 bit
%        fixdt('sfix77');      % Signed   77 bits
%
%     % using binary point scaling
%
%        fixdt('sfix32_En31');    % Fraction length 31  
%
%     % using slope and bias scaling
%
%        fixdt('ufix16_S5');          % TotalSlope 5 
%        fixdt('sfix16_B7');          % Bias 7
%        fixdt('ufix16_F1p5_En50');   % SlopeAdjustmentFactor 1.5  FixedExponent -50
%        fixdt('ufix16_S5_B7');       % TotalSlope 5, Bias 7
%        fixdt('sfix8_Bn125e18');     % Bias -125*10^18
%
%   Scaled Doubles
%
%     Scaled doubles data types are a testing and debugging feature. Scaled
%     doubles occur when two conditions are met.  First, an integer or 
%     fixed-point data type is entered into a Simulink block's mask. Second,
%     the dominant parent subsystem has data type override setting of scaled 
%     doubles.  When this happens, a data type like 'sfix16_En7' is overridden
%     with a scaled doubles data type 'flts16_En7'.  
%        The first output of FIXDT will be the same whether the original 
%     data type 'sfix16_En7' is passed in or its scaled doubles version
%     'flts16_En7' is passed in.  The optional second output argument 
%     is true if and only if the input is a scaled doubles data type.
%
%  Usage 5: Data Type Object converted to eval ready string
%
%   stringReadyForEval = FIXDT( DataTypeObject )
%  or
%   [stringReadyForEval,IsScaledDouble] = FIXDT( DataTypeObject )
%
%   The string that is returned is useful for configuring data types on blocks.
%
%   Examples: 
%
%       dataTypeObject   = fixdt(1,16,15);
%       stringReadyForEval = fixdt(dataTypeObject);
%       eval(stringReadyForEval);
%
%       open_system('fxpdemo_dbl2fix');
%       set_param('fxpdemo_dbl2fix/Dbl-to-FixPt','OutDataTypeStr',stringReadyForEval);
%
%   See also NUMERICTYPE, FLOAT.
 
% Copyright 1994-2023 The MathWorks, Inc.
%#codegen

if coder.target('MATLAB')
    % check the input argument in form as expected
    if nargin == 0
        DAStudio.error('modelexplorer:numericType:fixdtAtLeastOneInput'); 
    end
    
    if nargin > 7
        DAStudio.error('modelexplorer:numericType:fixdtInputArgsMustBeNoMoreThanSeven');
    end
    
    firstArgument = varargin{1};
    
    if nargin == 1 && ~ischar(firstArgument) && ~isstring(firstArgument)
        
        if isnumerictype(firstArgument) || isa(firstArgument, 'Simulink.NumericType')
    
            % return a string that can be evaluated to
            % reproduce an equivalent object
            %  except for Scaled Double
            %  for Scaled Double convert to equivalent Fixed Point Type
            %
            IsScaledDouble = firstArgument.isscaleddouble;
            
            if IsScaledDouble
                %  Change from Scaled Double to equivalent Fixed Point Type
                firstArgument.DataType = 'Fixed';
            end
    
            DataType = firstArgument.tostringInternalFixdt;
            
        elseif isstruct(firstArgument)      
            
            DataType = getdatatypespecs( firstArgument,[],0,0,4 );
            IsScaledDouble = false;
        else
            DAStudio.error('modelexplorer:numericType:fixdtJustOneArgMustBe');
        end
        
    else
        embeddedType = numerictype( varargin{:} );
        
        IsScaledDouble = embeddedType.isscaleddouble;
            
        if IsScaledDouble
            embeddedType.DataType = 'Fixed';
        end    
    
        DataType = Simulink.NumericType( embeddedType );
    end
else
    % Code generation path
    narginchk(1,7);
    coder.internal.assert(~isnumerictype(varargin{1}) && ~isa(varargin{1}, 'Simulink.NumericType')&&~isstruct(varargin{1}),'modelexplorer:numericType:fixdtCdrUnsupportedSingleArgument')
    embeddedType = numerictype( varargin{:} );
    IsScaledDouble = embeddedType.isscaleddouble;
    if IsScaledDouble
        DataType = numerictype(embeddedType, 'DataType', 'Fixed');
    else
        DataType = embeddedType;
    end
end

% LocalWords:  flts fltu Bn fxpdemo
