samer@4
|
1 % gatherer - API for autoexpanding arrays for accumulating data
|
samer@7
|
2 %
|
samer@7
|
3 % gatherer ::
|
samer@7
|
4 % [N,M]:[[1,2]] ~'size of elements to gather',
|
samer@7
|
5 % options {
|
samer@7
|
6 % init :: natural/512 ~'initial size of buffer';
|
samer@7
|
7 % grow :: natural/2 ~'factor by which to auto-expand buffer';
|
samer@7
|
8 % max :: natural/1e9 ~'maximum size of buffer'
|
samer@7
|
9 % }
|
samer@7
|
10 % -> struct {
|
samer@7
|
11 % remove :: natural => void ~'action to remove last n elements';
|
samer@7
|
12 % length :: void => natural ~'action to return current buffer length';
|
samer@7
|
13 % append :: [[N,M]] => void ~'action to append data to buffer';
|
samer@7
|
14 % collect :: void =>[[N,L]] ~'action to return buffer contents and reset';
|
samer@7
|
15 % }.
|
samer@4
|
16 function api=gatherer(size_in,varargin)
|
samer@37
|
17 opts=options('chunk',256,'init',512,'grow',2,'max',1e9,varargin{:});
|
samer@4
|
18 n=uint32(0);
|
samer@4
|
19 cap=opts.init; % initial capacity of buffer
|
samer@4
|
20 buf=zeros(size_in(1),cap); % buffer
|
samer@4
|
21
|
samer@4
|
22 api.remove=@remove;
|
samer@4
|
23 api.collect=@collect;
|
samer@4
|
24 api.length=@curlen;
|
samer@4
|
25
|
samer@4
|
26 if isnan(size_in(2)),
|
samer@4
|
27 api.append=@append;
|
samer@4
|
28 elseif size_in(2)>1,
|
samer@4
|
29 m=uint32(size_in(2)); M=1:m;
|
samer@4
|
30 api.append=@append_m;
|
samer@4
|
31 else
|
samer@4
|
32 api.append=@append_1;
|
samer@4
|
33 end
|
samer@4
|
34
|
samer@4
|
35 function l=curlen, l=n; end
|
samer@4
|
36 function remove(rem), n=n-rem; end
|
samer@4
|
37 function x=collect, x=buf(:,1:n); buf=[]; end
|
samer@4
|
38 function append_1(x)
|
samer@4
|
39 if n+1>cap, grow; end % need more room
|
samer@4
|
40 n=n+1; buf(:,n)=x;
|
samer@4
|
41 end
|
samer@4
|
42
|
samer@4
|
43 function grow
|
samer@4
|
44 if n>opts.max, error('maximum capacity exceeded'); end
|
samer@4
|
45 cap=opts.grow*cap;
|
samer@4
|
46 buf=repmat(buf,1,opts.grow);
|
samer@4
|
47 end
|
samer@4
|
48
|
samer@4
|
49 function append_var(x)
|
samer@4
|
50 chunk=size(x,2);
|
samer@4
|
51 if n+chunk>cap, grow; end % need more room
|
samer@4
|
52 buf(:,n+(1:chunk))=x;
|
samer@4
|
53 n=n+chunk;
|
samer@4
|
54 end
|
samer@4
|
55
|
samer@4
|
56 function append_m(x)
|
samer@4
|
57 if n+m>cap, grow; end % need more room
|
samer@4
|
58 buf(:,n+M)=x;
|
samer@4
|
59 n=n+m;
|
samer@4
|
60 end
|
samer@4
|
61 end
|