function vq = interp1(x, v, xq, method, extrap)
%INTERP1 1-D interpolation
%
%   Vq = INTERP1(X,V,Xq)
%   Vq = INTERP1(V,Xq)
%   Vq = INTERP1(X,V,Xq,METHOD)
%   Vq = INTERP1(V,Xq,METHOD)
%   Vq = INTERP1(X,V,Xq,METHOD,EXTRAPVAL)
%   Vq = INTERP1(V,Xq,METHOD,EXTRAPVAL)
%
%   Sample points input X must be a sorted vector.
%
%   METHOD must be 'linear' or 'nearest'.
%
%   EXTRAPVAL must be either a numeric scalar or 'extrap'. Option 'pp' is
%   not supported.
%
%   Only sample values input V can be a formatted dlarray. All other inputs
%   must be unformatted. If V is a formatted dlarray, query points input Xq
%   must be a vector, and the output Vq has the same data format as V.
%
%   See also INTERP1, DLARRAY.

%   Copyright 2020 The MathWorks, Inc.

if nargin == 2 || (nargin > 2 && ~isnumeric(xq))
    if nargin > 3
        extrap = method;
    end
    if nargin > 2
        method = xq;
    end
    xq = v;
    v = x;
    if isvector(v)
        x = 1:length(v);
    else
        x = 1:size(v, 1);
    end
    nargs = nargin + 1;
else
    nargs = nargin;
end

if nargs < 4
    method = "linear";
else
    if ~iPartialMatch(method, "linear") && ~iPartialMatch(method, "nearest")
        error(message('deep:dlarray:Interp1MethodNotSupported'))
    end
end

if nargs < 5
    extrap = NaN;
else
    if ~isnumeric(extrap) && ~iPartialMatch(extrap, "extrap")
        error(message('deep:dlarray:Interp1ExtrapNumeric'))
    end
end

dataX = iGetData(x);
[dataV, dimsV] = iGetDataV(v, isvector(xq));
dataXq = iGetData(xq);
dataExtrap = iGetData(extrap);

% Need to check that X is sorted (CPU supports this, but GPU does not)
if isa(dataX, 'deep.internal.recording.RecordingArray')
    dataXvalue = dataX.Value;
else
    dataXvalue = dataX;
end
if ~issorted(dataXvalue)
    error(message('deep:dlarray:Interp1GridNotSorted'))
end

dataVq = interp1(dataX, dataV, dataXq, method, dataExtrap);

vq = dlarray;
vq.FormattedData.Data = dataVq;
vq.FormattedData.DimensionMetadata = dimsV;


function tf = iPartialMatch(inputName, optionName)

tf = false;
if (ischar(inputName) && isrow(inputName)) || (isstring(inputName) && isscalar(inputName))
len = max(strlength(inputName), 1);
tf = strncmpi(inputName, optionName, len);
end

function dataX = iGetData(x)
% If input is a dlarray, return its underlying data in the "view"
% permutation.

if isa(x, 'dlarray')
    if ~isempty(x.FormattedData.DimensionMetadata)
        error(message('deep:dlarray:Interp1FormattedDlarray'))
    end
    
    dataX = x.FormattedData.Data;
    
    % Apply view permutation if necessary
    viewToData = x.ViewToDataMap;
    if ~isempty(viewToData)
        dataX = permute(dataX, viewToData);
    end
else
    dataX = x;
end


function [dataV, dimsV] = iGetDataV(v, isVectorXq)
% If input is a dlarray, return its underlying data in the "view"
% permutation.

dimsV = '';
if isa(v, 'dlarray')
    if ~isempty(v.FormattedData.DimensionMetadata)
        if isVectorXq
            dimsV = dims(v);
        else
            error(message('deep:dlarray:Interp1FormattedValues'));
        end
    end
    
    dataV = v.FormattedData.Data;
    
    % Apply view permutation if necessary
    viewToData = v.ViewToDataMap;
    if ~isempty(viewToData)
        dataV = permute(dataV, viewToData);
    end
else
    dataV = v;
end





