function varargout = pwelch(x,varargin)
%PWELCH Power Spectral Density estimate via Welch's method on the GPU.
%
%   Pxx = PWELCH(X)
%   Pxx = PWELCH(X,WINDOW)
%   Pxx = PWELCH(X,WINDOW,...,SPECTRUMTYPE)
%   Pxx = PWELCH(X,WINDOW,NOVERLAP)
%   [Pxx,W] = PWELCH(X,WINDOW,NOVERLAP,NFFT)
%   [Pxx,W] = PWELCH(X,WINDOW,NOVERLAP,W)
%   [Pxx,F] = PWELCH(X,WINDOW,NOVERLAP,NFFT,Fs)
%   [Pxx,F] = PWELCH(X,WINDOW,NOVERLAP,F,Fs)
%   [Pxx,F,Pxxc] = PWELCH(...,'ConfidenceLevel',P)
%   [...] = PWELCH(...,FREQRANGE)
%   [...] = PWELCH(...,TRACE)
%   PWELCH(...)
%
%   See also PWELCH, GPUARRAY.

%   Copyright 2019-2023 The MathWorks, Inc.

narginchk(1,9);
nargoutchk(0,3);

if nargin > 1
    [varargin{:}] = convertStringsToChars(varargin{:});
end

% Check if WINDOW or NFFT is on GPU
% WINDOW and NFFT are on GPU when each is a vector and a gpuArray
isNFFTSecondArg = false;
[windowOrNFFTOnGPU,windowIsVector,nfftIsVector,nfftArgInd,extraArgInd] = ...
    signal.internal.gpu.utilities.isWindowNFFTOnGPU(isNFFTSecondArg,varargin{:});

onGPU = false;
% Input signal, window (if it is a non-empty numeric vector), and NFFT
% (if it is a non-empty numeric vector) determine whether the
% calculation is done on the GPU and the output datatype.
if isgpuarray(x) || windowOrNFFTOnGPU
    onGPU = true;
    % Ensure that the input signal is on the GPU.
    x = gpuArray(x);
    % Check that a window vector has been provided. If so, ensure that
    % it is on the GPU.
    if windowIsVector
        varargin{1} = gpuArray(varargin{1});
    end
    % If a vector NFFT is provided, make sure it is on GPU
    if nfftIsVector
        varargin{nfftArgInd} = gpuArray(varargin{nfftArgInd});
    end
    % Gather all extra arguments if any
    [varargin{extraArgInd}] = gather(varargin{extraArgInd});
else
    % Gather all extra arguments.
    [varargin{:}] = gather(varargin{:});
end

% Dispatch in-memory pwelch if input signal is not gpuArray or input window
% vector is not gpuArray.
if ~onGPU
    varargout = cell(1,nargout);
    [varargout{:}] = pwelch(x,varargin{:});
    return;
end

funcName = 'pwelch';

% Possible outputs are:
%       Plot
%       Pxx
%       Pxx, freq
%       Pxx, freq, Pxxc
welchOut = cell(1,nargout);
[welchOut{1:nargout}] = welch(x,funcName,varargin{:});
varargout = cellfun(@real,welchOut,"UniformOutput",false);

end