function configurer = learnerCoderConfigurer(Mdl,X,varargin)
%LEARNERCODERCONFIGURER Create coder configurer for machine learning model
%
%   LEARNERCODERCONFIGURER returns the coder configurer for the machine learning
%   model MDL for code generation. Coder configurer also provides
%   functions for generating C/C++ code directly, or for generating
%   MATLAB files to be used for code generation.
%
%   CONFIGURER = LEARNERCODERCONFIGURER(MDL,X) returns a coder configurer
%   for the machine learning model MDL.
%
%   MDL can be a supported classification model and regression model. For
%   more details, see reference page for <a href="matlab:doc learnerCoderConfigurer">learnerCoderConfigurer</a>.
%
%   X is the predictor data for the 'predict' function of MDL, specified by an n-by-p
%   numeric matrix, where n is the number of observations and p is the number of
%   predictor variables.
%
%   CONFIGURER = LEARNERCODERCONFIGURER(MDL,X,'PARAM1',val1,'PARAM2',val2,...)
%   specifies optional parameter name-value pairs:
%       'NumOutputs'            - Number of the output arguments to return 
%                                 from the generated C/C++ code for the 
%                                 predict function of the machine
%                                 learning model MDL, specified as a positive integer.
%                                 Default value is 1.
%       'OutputFileName'        - File name of the generated C/C++ code,     
%                                 specified as a character vector or string.
%                                 The file name must not contain spaces because they
%                                 can lead to code generation failures in certain
%                                 operating system configurations. Also, the name
%                                 must be a valid MATLAB function name. Default
%                                 value is MDL object name plus 'Model'.
%       'Verbose'               - Verbosity level, specified as true (logical 1)
%                                 or false (logical 0). The verbosity level controls the
%                                 display of notification messages at the command line
%                                 for the coder configurer. If true, notification
%                                 messages are displayed when changes to the coder attributes
%                                 of a parameter result in changes for other dependent
%                                 parameters. If false, notifications are
%                                 not displayed. Default value is true.
%     'ObservationsIn'          - Predictor data observation dimension, specified as 'rows' or
%                                 'columns'. Default value is 'rows'. If 'columns', predictor data
%                                 X must be oriented so that the observations correspod to columns.
%
%
%   Example 1: Train a Classification SVM model on data with two classes
%              and get a ClassificationSVMCoderConfigurer for configuring
%              the model's update and predict parameters:
%
%       % Train SVM model
%       load ionosphere;
%       svm = fitcsvm(X,Y,'Standardize',true,'KernelFunction','rbf',...
%               'KernelScale','auto');
%
%       % Create ClassificationSVMCoderConfigurer
%       svmCoderConfigurer = learnerCoderConfigurer(svm,X,'NumOutputs',2);
%
%       % Configure ClassificationSVMCoderConfigurer
%       svmCoderConfigurer.Alpha.SizeVector = [200, 1];
%       svmCoderConfigurer.Alpha.VariableDimensions = [true false];
%       svmCoderConfigurer.OutputFileName = 'SVMModel';
%       % generate code for MEX target
%       generateCode(svmCoderConfigurer,'mex');
%
%
%   Example 2: Train a Regression SVM model and get a RegressionSVMCoderConfigurer
%   for configuring the model's predict parameters:
%
%       load carsmall;
%       X = [Horsepower,Weight];
%       Y = MPG;
%       svm = fitrsvm(X,Y);
%
%       % Create RegressionSVMCoderConfigurer
%       svmCoderConfigurer = learnerCoderConfigurer(svm,X,'Verbose',true);
%
%       % generate code for LIB target
%       generateCode(svmCoderConfigurer,'lib');
%
%   See also classreg.learning.coder.config.svm.ClassificationSVMCoderConfigurer,
%   classreg.learning.coder.config.svm.RegressionSVMCoderConfigurer,
%   classreg.learning.coder.config.ClassificationECOCCoderConfigurer.

%   Copyright 2018-2022 The MathWorks, Inc.

try
    if (isa(Mdl,'classreg.learning.classif.CompactClassificationSVM') || isa(Mdl,'classreg.learning.regr.CompactRegressionSVM')) &&...
            strcmp(Mdl.KernelParameters.Function, 'linear') && ~isempty(Mdl.Alpha)
        warning(message('stats:classreg:coderutils:save:KeepSupportVectorsForCodegen', 'learnerCoderConfigurer'));
    end
    if  isa(Mdl,'classreg.learning.classif.CompactClassificationSVM')
        configurer = classreg.learning.coder.config.svm.ClassificationSVMCoderConfigurer.fromObject(Mdl,X,varargin{:});
    elseif isa(Mdl,'classreg.learning.regr.CompactRegressionSVM')
        configurer = classreg.learning.coder.config.svm.RegressionSVMCoderConfigurer.fromObject(Mdl,X,varargin{:});
    elseif isa(Mdl,'classreg.learning.classif.CompactClassificationECOC') 
        configurer = classreg.learning.coder.config.ClassificationECOCCoderConfigurer.fromObject(Mdl,X,varargin{:});
    elseif isa(Mdl,'ClassificationLinear') 
        configurer = classreg.learning.coder.config.linear.ClassificationLinearCoderConfigurer.fromObject(Mdl,X,varargin{:});    
    elseif isa(Mdl,'RegressionLinear') 
        configurer = classreg.learning.coder.config.linear.RegressionLinearCoderConfigurer.fromObject(Mdl,X,varargin{:});
    elseif isa(Mdl,'classreg.learning.classif.CompactClassificationTree') 
        configurer = classreg.learning.coder.config.tree.ClassificationTreeCoderConfigurer.fromObject(Mdl,X,varargin{:});    
    elseif isa(Mdl,'classreg.learning.regr.CompactRegressionTree') 
        configurer = classreg.learning.coder.config.tree.RegressionTreeCoderConfigurer.fromObject(Mdl,X,varargin{:});          
    else
        error(message('stats:coder:config:config:UnsupportedModel'));
    end
catch ME
    throw(ME);
end
end