
function f = bsscreateinterpolant(bss, evalfun, gridpointspp)
%BSSCREATEINTERPOLANT Create a gridded interpolant for a PDF or CDF
%
% INPUTS:
%
%    bss:
%       The B-Spline series data structure containing the series to be used
%       for evaluation and the creation of the grid.
%
%    evalfun:
%       The function that is to be evaluated. If the B-Spline series
%       represents a probability density function, the output functions
%       'pdf' and 'cdf' are available for the grid.
%
%       If no evaluation function is specified or the evaluation function
%       is empty the 'pdf' evaluation function will be used.
%
%       Allowed evaluation functions if the B-Spline series represents a
%       probability density function:
%
%          pdf      : The probability density function, f(x)
%          cdf      : The cumulative distribution function, F(x)
%
%    ngridpointspp:
%       The number of grid points per partition to use when creating the
%       gridded interpolant.
%
% OUTPUTS:
%
%    f:
%       The gridded interpolant function.
%

%
% Copyright 2014-2023 Biometrics Northwest LLC
%

%
% Modified: 2023-05-06
% Author  : Kevin R. Gehringer
%
%    Added an argument for the number of grid points per partition.
%
% Modified: 2023-03-11
% Author  : Kevin R. Gehringer
%
%    Removed 'bss' as a valid evaluation function.
%
%    Switched to using a small memory footprint for the evaluation at the
%    grid points rather than generating the entire grid and evaluating it.s
%
% Modified: 2018-08-28
% Author  : Kevin R. Gehringer
%
%     Changed the name of a varialbe from 'ngrid' to 'tmpngrid. MATLAB has
%     a function called 'ngrid' that caused a potentlai conflict.
%
% Created: 2016-05-14
% Author : Kevin R. Gehringer
%

%
% We gotta have a B-spline series structure.
%
if ( ~exist('bss','var') )
   error('The B-spline series data structure was not provided.');
end

if ( isempty(bss) )
   error('The B-spline series data structure was empty.');
end

%
%   Check to see if an evaluation function was not specified or was empty.
%   If not specified or it is empty, assign the default value of 'pdf'.
%
if ( ~exist('evalfun','var') )
    evalfun = 'pdf';
else
    if ( isempty(evalfun) )
        evalfun = 'pdf';
    end
end

%
% Validate the evaluation function. Valid values are: 'pdf', and
% 'cdf'.
%
okfuns = {'pdf';'cdf'};
if ( ~any(strcmpi(evalfun,okfuns)) )
    error('The evaluation function ''%s'' was not recognized.',evalfun);
end

%
% Compute the size for the gridded interpolant.
%
if ( isscalar(gridpointspp) )
    tmpngrid = floor(gridpointspp*bss.partition.n)+1;
else
    tmpngrid = floor(gridpointspp.*bss.partition.n)+1;
end

%
% Check available memory to see if the gridded interpolant will likely fit
%
bsscheckmemory(tmpngrid,'grid');

%
% Create the xgrid as a compact grid in a cell array.
%
xgrid = cell(bss.ndim,1);
for idim = 1:bss.ndim
    xgrid{idim} = linspace(bss.bnds(idim,1),bss.bnds(idim,2),tmpngrid(idim))';
end

%ygrid = bssgrideval(xgrid,bss,evalfun);
%xg = bssgridpoints(xgrid);
%[ygrid,xg2] = bssgridevalc(xgrid,bss,evalfun);
ygrid = bssgridevalc(xgrid,bss,evalfun);
%sum(xg-xg2)

if ( bss.ndim > 1)
    %
    % tmpngrid must be a row vector for reshaping; it is always a column
    % since bss.partition.n is always a column, so just transpose it.
    %
    ygrid = reshape(ygrid,tmpngrid');
end

f = griddedInterpolant(xgrid,ygrid,'linear');

end