function v=stack2mat(s,n)
% stack/stack2mat: converts a stack to a matrix
% usage: v=stack2mat(s)
% v=stack2mat(s,n)
%
% s is either an empty cell array or of the form {x,s1} where s1 is a stack
% and all the elements x must be of the same size.
%
% stack2mat(s,n) concatenates all the elements of s along the first
% dimension of size 1, with the elements in the same order that they were
% pushed onto the stack. n is the number of elements of the stack.
% An error results if the sizes of the elements are not equal.
%
% stack2mat(s) determines n automatically but is up to 2x slower to run,
% as it requires an additional pass through the stack.
%
% If you are confident that the sizes of the elements all agree, it may be
% quicker to use cell2mat(stack2mat(s)).
%
% Example: create (1:n)', using a stack:
% s={};
% n=1e5;
% for i=1:n
% s=push(i,s);
% end;
% v = stack2mat(s);
% isequal(v,(1:n)') % should be 1
%
% See also: push, pop, stack2cell
% Author: Ben Petschel 28/8/2009
% Version history:
% 28/8/2009 - first release
if nargin==2
% length of stack is given
if isempty(s) || n==0
v = [];
else
[x,s]=pop(s);
% now put all the x in a matrix, if the sizes all agree
sx=size(x);
sok=true; % true if size of vectors in stack are same
dim=find(sx==1,1,'first');
if isempty(dim)
dim=numel(sx)+1;
ndim=dim;
else
ndim=numel(sx);
end;
sv=sx;
sv(dim)=n;
v=zeros(sv);
ind=repmat({':'},1,ndim);
ind{dim}=n;
v(ind{:})=x;
n=n-1;
while n>0 && ~isempty(s)
% keep popping until stack is empty or matrix is filled
[x,s]=pop(s);
if all(size(x)==sx)
ind{dim}=n;
v(ind{:})=x;
else
sok = false;
break;
end;
n=n-1;
end;
if ~sok
error('stack:stack2mat:elemdim','dimensions of the stack elements do not agree');
end;
end;
if n>0 || ~isempty(s)
% stack emptied before matrix filled, or vice-versa
warning('stack:stack2mat:stacksize','actual and provided stack sizes do not agree');
end;
else
% have to determine the length (height) of the stack
if isempty(s)
v=[];
else
[x,t]=pop(s);
n=1;
sx=size(x);
sok=true; % true if size of vectors in stack are same
% find the depth of s and check that all x are same size
while ~isempty(t)
[x,t]=pop(t);
n=n+1;
if any(size(x)~=sx)
sok=false;
break;
end;
end;
% now put all the x in a matrix, if the sizes were ok
if sok
dim=find(sx==1,1,'first');
if isempty(dim)
dim=numel(sx)+1;
ndim=dim;
else
ndim=numel(sx);
end;
sv=sx;
sv(dim)=n;
v=zeros(sv);
ind=repmat({':'},1,ndim);
while ~isempty(s)
ind{dim}=n;
[x,s]=pop(s);
v(ind{:})=x;
n=n-1;
end;
else
error('stack:stack2mat:elemdim','dimensions of the stack elements do not agree');
end;
end;
end;
end