function s = collapse(t,dims,fun)
%COLLAPSE Collapse sptensor values along specified dimensions.
%
%   S = COLLAPSE(T,DIMS) sums the entries of T along all dimensions
%   specified in DIMS. If DIMS is negative, then T is summed across
%   all dimensions *not* specified by -DIMS. If T.type is 'incomplete',
%   then the missing entries are ignored.
%
%   S = COLLAPSE(T) is shorthand for S = COLLAPSE(T,1:ndims(T)).
%
%   S = COLLAPSE(T,DIMS,FUN) accumulates the entries of T using the
%   accumulation function @FUN. Any zero or missing entries in T are 
%   ignored.
%
%   Examples
%   subs = [1 1 1; 1 1 3; 2 2 4; 4 4 4]
%   vals = [10.5; 1.5; 2.5; 3.5]
%   X = sptensor(subs,vals,[4 4 4]);
%   Y = collapse(X,[2 3]) %<-- sum of entries in each mode-1 slice
%   Y = collapse(ones(X),[1 2]) %<-- nnz in each mode-3 slide
%   Y = collapse(ones(X),[1 2],@max) %<-- 1 if mode-3 has any entry
%   Y = collapse(ones(X),-3,@max); %<-- equivalent
%
%   <a href="matlab:web(strcat('file://',fullfile(getfield(what('tensor_toolbox'),'path'),'doc','html','collapse_scale_doc.html')))">Documentation page for collapsing and scaling tensors</a>
%
%   See also SPTENSOR, SPTENSOR/SCALE.
%
%Tensor Toolbox for MATLAB: <a href="https://www.tensortoolbox.org">www.tensortoolbox.org</a>



if ~exist('fun', 'var')
    fun = @sum;
end

if ~exist('dims', 'var')
    dims = 1:ndims(t);
end

dims = tt_dimscheck(dims,ndims(t));
remdims = setdiff(1:ndims(t),dims);

% Check for the case where we accumulate over *all* dimensions
if isempty(remdims)
    s = fun(t.vals);
    return;
end

% Calculate the size of the result
newsiz = size(t,remdims);

% Check for the case where the result is just a dense vector
if numel(remdims) == 1
    if ~isempty(t.subs)
        s = accumarray(t.subs(:,remdims), t.vals, [newsiz 1], fun);
    else
        s = zeros(newsiz,1);
    end
    return;
end

% Create the result
if ~isempty(t.subs)
  s = sptensor(t.subs(:,remdims), t.vals, newsiz, fun, t.type);
else
  s = sptensor([],[],newsiz,t.type,0);
end
