samer@4: % gatherer - API for autoexpanding arrays for accumulating data samer@7: % samer@7: % gatherer :: samer@7: % [N,M]:[[1,2]] ~'size of elements to gather', samer@7: % options { samer@7: % init :: natural/512 ~'initial size of buffer'; samer@7: % grow :: natural/2 ~'factor by which to auto-expand buffer'; samer@7: % max :: natural/1e9 ~'maximum size of buffer' samer@7: % } samer@7: % -> struct { samer@7: % remove :: natural => void ~'action to remove last n elements'; samer@7: % length :: void => natural ~'action to return current buffer length'; samer@7: % append :: [[N,M]] => void ~'action to append data to buffer'; samer@7: % collect :: void =>[[N,L]] ~'action to return buffer contents and reset'; samer@7: % }. samer@4: function api=gatherer(size_in,varargin) samer@37: opts=options('chunk',256,'init',512,'grow',2,'max',1e9,varargin{:}); samer@4: n=uint32(0); samer@4: cap=opts.init; % initial capacity of buffer samer@4: buf=zeros(size_in(1),cap); % buffer samer@4: samer@4: api.remove=@remove; samer@4: api.collect=@collect; samer@4: api.length=@curlen; samer@4: samer@4: if isnan(size_in(2)), samer@4: api.append=@append; samer@4: elseif size_in(2)>1, samer@4: m=uint32(size_in(2)); M=1:m; samer@4: api.append=@append_m; samer@4: else samer@4: api.append=@append_1; samer@4: end samer@4: samer@4: function l=curlen, l=n; end samer@4: function remove(rem), n=n-rem; end samer@4: function x=collect, x=buf(:,1:n); buf=[]; end samer@4: function append_1(x) samer@4: if n+1>cap, grow; end % need more room samer@4: n=n+1; buf(:,n)=x; samer@4: end samer@4: samer@4: function grow samer@4: if n>opts.max, error('maximum capacity exceeded'); end samer@4: cap=opts.grow*cap; samer@4: buf=repmat(buf,1,opts.grow); samer@4: end samer@4: samer@4: function append_var(x) samer@4: chunk=size(x,2); samer@4: if n+chunk>cap, grow; end % need more room samer@4: buf(:,n+(1:chunk))=x; samer@4: n=n+chunk; samer@4: end samer@4: samer@4: function append_m(x) samer@4: if n+m>cap, grow; end % need more room samer@4: buf(:,n+M)=x; samer@4: n=n+m; samer@4: end samer@4: end