Mercurial > hg > ishara
changeset 36:9e7be347b3a0
Renamed sequence classes to avoid clashes with seq methods;
Fixed default slicing dimension while retaining behaviour of window.m;
Updated use of sequences in dsp/synth.
line wrap: on
line diff
--- a/audio/playaudio_async.m Mon Jan 21 11:01:45 2013 +0000 +++ b/audio/playaudio_async.m Thu Jan 24 14:51:23 2013 +0000 @@ -2,7 +2,7 @@ % % playaudio :: % X:seq [[N]] ~'sequence of arrays', -% R:nonneg ~'sampling rate', +% sink(1,R) ~'single channel sink', % options { % maxbuf :: natural/2*max(size(X)) ~'maximum buffer size'; % hook :: (iterator(S)->iterator(T)) ~'fn to build iterator'; @@ -40,5 +40,5 @@ % NB: all the audio buffers must be the same size for this to work. % NB: the rewind function should only be called when the timer is stopped. function [Sched,GetData]=playaudio_async(Y,Snk,varargin) - [Sched,GetData]=playaudio_unfold(size(Y,2),@decons,Y,Snk),varargin{:}); + [Sched,GetData]=playaudio_unfold(size(Y,2),@decons,Y,Snk,varargin{:}); end
--- a/audio/playaudio_unfold.m Mon Jan 21 11:01:45 2013 +0000 +++ b/audio/playaudio_unfold.m Thu Jan 24 14:51:23 2013 +0000 @@ -4,7 +4,7 @@ % playaudio :: % N:natural ~'buflen', % (S->[[C,N]],S) ~'unfolding function', -% sink(C,N) ~'sink', +% sink(C,R) ~'sink for C channels', % options { % maxbuf :: natural/2*max(size(X)) ~'maximum buffer size'; % hook :: (iterator(S)->iterator(T)) ~'fn to build iterator';
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dsp/README.txt Thu Jan 24 14:51:23 2013 +0000 @@ -0,0 +1,66 @@ +*** DSP tools +*** Summary of functions + +The is some duplication of code in this toolbox; some of the code is obsolete +and will be deleted or merged into other functions at some point. + +FREQUENCY DECOMPOSITIONS + +Discrete Fourier transform + dftbins - Returns number of bins to retain for real DFT of length N + dftbw - Normalised bandwidths of bands in a DFT + dftfmap - Frequency map for DFT of real signal + dftmap - fmap, standard usage for DFT + freqscale - return frequency scale for FFT analysis + + fouriermat - return N*N real fourier basis + realfft - Do FFT assuming real data, returning complex half spectrum + powspec - power spectra of columns of x + magspec - get magnitude spectra of columns of x (v. 2) + phasespec - get phase spectra of columns of x + imagspec - convert mag/phase spectrum to wave + ipowspec - convert power/phase spectrum to wave + mag_phase_join - get mag and phase spectra and recombine to signal + mag_phase_split - arrow to get FFT and do mag/phase split + specgrm - Time-Varying Spectrum + phasedata - Spectral data from buffered frames + spectraldata - Spectral data from buffered frames + + spec2ac - convert power spectrum to autocorrelation sequence + spec2fir - convert magnitude spectra to FIR filter coefficients + specdist - spectral distance using I-S divergence + +Constant-Q + constq - Constant Q spectrogram. + cqbasis - Audio Spectrum linear to log frequency map + cqedges - Audio Spectrum linear to log frequency map (no checking) + +Mel scale + lin2mel - matrix to warp linear scale power spectra to mel scale + hz2mel - Convert frequencies from Hertz to mel scale. + mel2hz - Convert frequencies from mel scale to Hertz. + melspace - create array of frequencies evenly spaced in mel scale + +Cepstrum + cepstrum - generalised cepstral coefficients from warped power spectrogram + mfcc - Mel-frequency ceptral coefficients + mk_mfcc - Function factory, makes MFCC functions + +Wigner distribution + wigner - Wigner-Ville Distribution. + wignerdata - sliding window wigner distribution. + +OTHER TOOLS + zeropad - Function to zero pad a signal + expwin - Exponential window + oggwin - Ogg-vorbis window. + sinewin - Sine window. + linlogspace - joined linear/log map + formants - Compute formants from LPC coefficients + fq2poles - resonant frequencies to poles + hann_filterbank - Bank of Hanning (raised cosine) filters + tri_filterbank - Bank of triangular filters + tri_filterbank_aa - Bank of anti-aliased triangular filters + specbasis + unbuffer - overlap-and-add signal reconstruction (opposite of buffer) + frames - Buffer signal, like buffer, but using hop instead of overlap
--- a/dsp/synth/addsynth.m Mon Jan 21 11:01:45 2013 +0000 +++ b/dsp/synth/addsynth.m Thu Jan 24 14:51:23 2013 +0000 @@ -9,5 +9,5 @@ % -> seq([[1,N]]) ~'sum of components'. phi=repmat_to(phi,size(F)); -y=sum(zipdata(@(a,x)spdiag(a)*x,2,A,blockdata(msine,N,phi,F)),1); +y=zipwith(@(a,x)a'*x,A,blockdata(msine,N,phi,F));
--- a/dsp/synth/audio_sonifier.m Mon Jan 21 11:01:45 2013 +0000 +++ b/dsp/synth/audio_sonifier.m Thu Jan 24 14:51:23 2013 +0000 @@ -28,18 +28,12 @@ % dispose :: void => void % }. -function f=audio_sonifier(device,dur,varargin) +function f=audio_sonifier(dur,varargin) audio_info = prefs( ... 'transpose',0,'gen','sine','fs',11025, 'cutoff',0.4, ... 'attack',5,'decay',200,'release',5,varargin{:}); - if isempty(device) - audio_info.lineout = lineout(1,audio_info.fs); - else - audio_info.lineout = device; - audio_info.fs = rate(device); - end - + audio_info.lineout = lineout(1,audio_info.fs); f=@(seq,onfinish)sonify_audio(audio_info,dur,seq,onfinish); end
--- a/dsp/synth/blockdata.m Mon Jan 21 11:01:45 2013 +0000 +++ b/dsp/synth/blockdata.m Thu Jan 24 14:51:23 2013 +0000 @@ -18,11 +18,7 @@ nargs=length(varargin)+1; params=cellmap(@dd,varargin); % make sure all input sequences actually are perm=[nargs+1,1,2:nargs]; - x=zipaccum(@blockgen,s0,[{dd(dur)},params]); - - % !! NOTE: it would also be possible to NOT maintain state between calls, - % so that each block would start from the same initial state - % x=zipwith(@blockgen_nostate,dd(dur),params{:}); + x=zipaccum(@blockgen,s0,dd(dur),params{:}); function [y,state]=blockgen(varargin) % this is weird - for some reason Matlab crashes if I call block
--- a/dsp/synth/shepardtone.m Mon Jan 21 11:01:45 2013 +0000 +++ b/dsp/synth/shepardtone.m Thu Jan 24 14:51:23 2013 +0000 @@ -17,7 +17,7 @@ fc=0.25; if nargin<4, H=(-10:1)'; else H=H(:); end -F=fndata(@(c)fc*2.^(H+mod(c,1)),C); % frequencies -A=fndata(prof,F); % component amplitudes +F=map(@(c)fc*2.^(H+mod(c,1)),C); % frequencies +A=map(prof,F); % component amplitudes y=addsynth(N,A,F,0);
--- a/dsp/synth/sonify.m Mon Jan 21 11:01:45 2013 +0000 +++ b/dsp/synth/sonify.m Thu Jan 24 14:51:23 2013 +0000 @@ -36,10 +36,10 @@ num2hz=@(n)nan2x(0,fm*2.^((n+tr)/12)); if isscalar(D), D=dm*D; - else D=fndata(@(d)dm*d,dd(D),'compose',1); % D=dm*D with optimisation + else D=map(@(d)dm*d,dd(D)); % D=dm*D with optimisation end - C=fndata(@(n)(n+tr)/12,dd(S),'compose',1); % chroma values - F=fndata(num2hz,dd(S),'compose',1); % convert to normalised frequencies + C=map(@(n)(n+tr)/12,dd(S)); % chroma values + F=map(num2hz,dd(S)); % convert to normalised frequencies % cutoff for band-limited waveform generation if isempty(opts.bl_cutoff) @@ -55,7 +55,7 @@ case 'blsquare' % cumsum within each buffer: doesn't drift but makes % audible clicks between buffers. - Y=fndata(@(t)0.5*cumsum(t),blockdata(bpblit,D,0,cutoff,F)); + Y=map(@(t)0.5*cumsum(t),blockdata(bpblit,D,0,cutoff,F)); case 'blsquare2' % this version does cumsum across the sequence to remove % discontinuities but requires high-pass filter to stop drift. @@ -71,13 +71,13 @@ % if supplied apply envelope to shape each note if nargin>2 && ~isempty(env), - ad=fndata(env,Y,'sizecheck',1); + ad=map(env,Y); else ad=Y; end % rebuffer to constant size if ~isempty(opts.buffer) - ad=windowdata(ad,ceil(opts.buffer*opts.fs)); + ad=window(ad,ceil(opts.buffer*opts.fs)); end
--- a/dsp/synth/sonify_disc.m Mon Jan 21 11:01:45 2013 +0000 +++ b/dsp/synth/sonify_disc.m Thu Jan 24 14:51:23 2013 +0000 @@ -17,14 +17,14 @@ dm=60*opts.fs/opts.bpm; if isscalar(D), D=dd(dm*D); - else D=fndata(@(d)dm*d,dd(D),'compose',1); % D=dm*D with optimisation + else D=map(@(d)dm*d,dd(D)); % D=dm*D with optimisation end - Y=zipdata(@select_gen,2,D,dd(S)); + Y=zipwith(@select_gen,D,dd(S)); % if supplied apply envelope to shape each note if ~isempty(opts.env), - Y=fndata(opts.env,Y,'sizecheck',1); + Y=map(opts.env,Y); end % rebuffer to constant size
--- a/dsp/synth/srdata.m Mon Jan 21 11:01:45 2013 +0000 +++ b/dsp/synth/srdata.m Thu Jan 24 14:51:23 2013 +0000 @@ -14,7 +14,7 @@ % also to supply the generator with a sequence of parameter % values. - x=mapaccum(@blockgen,s0,zip(varargin{:}),'sizecheck',1); + x=mapaccum(@blockgen,s0,zip(varargin{:})); function [y,state]=blockgen(theta,state) % this is weird - for some reason Matlab crashes if I call block
--- a/dsp/synth/unbuffer_nu.m Mon Jan 21 11:01:45 2013 +0000 +++ b/dsp/synth/unbuffer_nu.m Thu Jan 24 14:51:23 2013 +0000 @@ -6,7 +6,7 @@ % -> seq([[1,_]]) ~'sequence of de-overlapped frames'. function Y=unbuffer_nu(X,hop) - Y=zipaccum(@olap,{hop,X},[]); + Y=zipaccum(@olap,[],hop,X); function [y,s1]=olap(hop,x,s) ls=length(s);
--- a/general/fileutils/loadmat.m Mon Jan 21 11:01:45 2013 +0000 +++ b/general/fileutils/loadmat.m Thu Jan 24 14:51:23 2013 +0000 @@ -14,6 +14,8 @@ % Vararg form (not well typed) % % [X,Y,Z,...]=loadmat(Filename,var1,var2,var,...); +% +% NB. Matlab's load can now do this. load(file); for j=1:length(varargin)
--- a/sequences/+seq/bindcat.m Mon Jan 21 11:01:45 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -% bindcat - sort of monadic bind for sequences. -% -% bindcat :: -% seq(A) ~ 'the first sequence', -% (A->seq(A)) ~ 'function to return second sequence given last element of first' -% -> seq(A) ~ 'resultant sequence'. -% -% The resulting sequence consists of the entire sequence represented by the -% first parameter, followed by the sequence obtained by applying the second -% parameter to the last element of the first sequence. -% -% Example: -% -% gather(2,bindcat(cellseq({1,2,3,4}),@(x)take(head(x),0))) -% -% ans = 1 2 3 4 0 0 0 0 -classdef bindcat < seq - properties (GetAccess=private, SetAccess=private) - source - nfn - x - end - methods - function o=bindcat(X,F) - o.source=X; - o.nfn=F; - o.x=head(X); - end - - function z=elsize(o), z=size(o.x); end - function s=tostring(o), s=sprintf('%s >>= %s',tostring(o.source),tostring(o.nfn)); end - function x=head(o), x=o.x; end - function o=next(o), - o.source=next(o.source); - if isempty(o.source), o=o.nfn(o.x); - else o.x=head(o.source); - end - end - end -end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sequences/+seq/binder.m Thu Jan 24 14:51:23 2013 +0000 @@ -0,0 +1,40 @@ +% binder - sort of monadic bind for sequences. +% +% binder :: +% seq(A) ~ 'the first sequence', +% (A->seq(A)) ~ 'function to return second sequence given last element of first' +% -> seq(A) ~ 'resultant sequence'. +% +% The resulting sequence consists of the entire sequence represented by the +% first parameter, followed by the sequence obtained by applying the second +% parameter to the last element of the first sequence. +% +% Example: +% +% gather(2,bindcat(cellseq({1,2,3,4}),@(x)take(head(x),0))) +% +% ans = 1 2 3 4 0 0 0 0 +classdef binder < seq + properties (GetAccess=private, SetAccess=private) + source + nfn + x + end + methods + function o=binder(X,F) + o.source=X; + o.nfn=F; + o.x=head(X); + end + + function z=elsize(o), z=size(o.x); end + function s=tostring(o), s=sprintf('%s >>= %s',tostring(o.source),tostring(o.nfn)); end + function x=head(o), x=o.x; end + function o=next(o), + o.source=next(o.source); + if isempty(o.source), o=o.nfn(o.x); + else o.x=head(o.source); + end + end + end +end
--- a/sequences/+seq/buffer.m Mon Jan 21 11:01:45 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -% buffer - collect elements of sequence into sequence of arrays -% -% seq.buffer.make :: -% seq([Size:[[1,E]]]) ~'sequence of E dimensional arrays', -% L:natural ~'buffer width', -% E:natural ~'effective dimension of input values', -% buffer_tailfn ~'function to deal with last incomplete buffer' -% -> seq([[Size,L]]) ~'buffered sequence (no-overlapping)'. -% -% buffer_tailfn can be -% seq.buffer.truncate :: void -> tailfn ~'discard incomplete buffer'. -% seq.buffer.append :: void -> tailfn ~'append smaller buffer to sequence'. -% seq.buffer.pad :: [[N]]-> tailfn ~'pad final buffer with value'. - -classdef buffer < seq - properties (GetAccess=private, SetAccess=immutable) - width - colons - tailfn - end - properties (GetAccess=private, SetAccess=private) - source - buf - end - - methods (Static) - function a=make(source,L,dim,tailfn) - if isempty(source), a=nil; - else - sz=size1(source); - if nargin<3, dim=length(sz); end - if nargin<4, tailfn=seq.buffer.truncate; end - buf1=repmat(head(source),tosize([ones(1,dim),L])); - a=read(seq.buffer(next(source),L,dim,tailfn,buf1),2,L); - end - end - - function f=truncate, f=@(buf,i,colons)nil; end - function f=append, f=@(buf,i,colons)singleton(buf(colons{:},1:i)); end - function f=pad(x), f=@padfn; - function s=padfn(buf,i,colons) - L=size(buf,length(colons)+1); - buf(colons{:},i+1:L)=repmat(x,tosize([ones(size(colons)),L-i])); - s=singleton(buf); - end - end - end - - methods - function z=elsize(a), z=size(a.buf); end - function s=tostring(a), s=sprintf('%s >> buffer(%d,%d)',tostring(a.source),a.width,length(a.colons)+1); end - function x=head(a), x=a.buf; end - function a=next(a), a=read(a,1,a.width); end - end - - methods (Access=private) - function a=buffer(source,L,dim,tailfn,buf) - a.source = source; - a.width = L; - a.colons = repmat({':'},1,dim); - a.tailfn = tailfn; - a.buf = buf; - end - - function a=read(a,N,M) - % read next lot of values and make an array - for i=N:M - if isempty(a.source), a=a.tailfn(a.buf,i-1,a.colons); return; end - a.buf(a.colons{:},i)=head(a.source); - a.source=next(a.source); - end - end - end -end -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sequences/+seq/bufferer.m Thu Jan 24 14:51:23 2013 +0000 @@ -0,0 +1,76 @@ +% bufferer - collect elements of sequence into sequence of arrays +% +% seq.bufferer.make :: +% seq([Size:[[1,E]]]) ~'sequence of E dimensional arrays', +% L:natural ~'buffer width', +% E:natural ~'effective dimension of input values', +% buffer_tailfn ~'function to deal with last incomplete buffer' +% -> seq([[Size,L]]) ~'buffered sequence (no-overlapping)'. +% +% buffer_tailfn can be +% seq.bufferer.truncate :: void -> tailfn ~'discard incomplete buffer'. +% seq.bufferer.append :: void -> tailfn ~'append smaller buffer to sequence'. +% seq.bufferer.pad :: [[N]]-> tailfn ~'pad final buffer with value'. + +classdef bufferer < seq + properties (GetAccess=private, SetAccess=immutable) + width + colons + tailfn + end + properties (GetAccess=private, SetAccess=private) + source + buf + end + + methods (Static) + function a=make(source,L,dim,tailfn) + if isempty(source), a=nil; + else + sz=size1(source); + if nargin<3, dim=length(sz); end + if nargin<4, tailfn=seq.bufferer.truncate; end + a=read(seq.bufferer(source,L,dim,tailfn),2,L); + end + end + + function f=truncate, f=@(buf,i,colons)nil; end + function f=append, f=@(buf,i,colons)singleton(buf(colons{:},1:i)); end + function f=pad(x), f=@padfn; + function s=padfn(buf,i,colons) + L=size(buf,length(colons)+1); + buf(colons{:},i+1:L)=repmat(x,tosize([ones(size(colons)),L-i])); + s=singleton(buf); + end + end + end + + methods + function z=elsize(a), z=size(a.buf); end + function s=tostring(a), s=sprintf('%s >> buffer(%d,%d)',tostring(a.source),a.width,length(a.colons)+1); end + function x=head(a), x=a.buf; end + function a=next(a), a=read(a,1,a.width); end + + function a=bufferer(source,L,dim,tailfn) + buf=repmat(head(source),tosize([ones(1,dim),L])); + a.source = next(source); + a.width = L; + a.colons = repmat({':'},1,dim); + a.tailfn = tailfn; + a.buf = buf; + end + + end + + methods (Access=private) + function a=read(a,N,M) + % read next lot of values and make an array + for i=N:M + if isempty(a.source), a=a.tailfn(a.buf,i-1,a.colons); return; end + a.buf(a.colons{:},i)=head(a.source); + a.source=next(a.source); + end + end + end +end +
--- a/sequences/+seq/cache.m Mon Jan 21 11:01:45 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -% cache- Cache each buffer to speed up multiple reads -% -% cache :: seq(A) -> seq(A). -% -% The idea is that the data is cached on each call to next, -% so that reading the array does not require calls to source. -classdef cache < seq - properties (GetAccess=private, SetAccess=private) - source - x - end - methods - function o=cache(source), o.source=source; o.x=head(source); end - function x=head(o), x=o.x; end - function s=tostring(o), s=['cache(',tostring(o.source),')']; end - function z=elsize(o), z=size(o.x); end - function o=next(o) - o.source=next(o.source); - if ~isempty(o.source), o.x=head(o.source); else o=o.source; end - end - end -end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sequences/+seq/cacher.m Thu Jan 24 14:51:23 2013 +0000 @@ -0,0 +1,22 @@ +% cacher- Cache each buffer to speed up multiple reads +% +% cacher :: seq(A) -> seq(A). +% +% The idea is that the data is cached on each call to next, +% so that reading the array does not require calls to source. +classdef cacher < seq + properties (GetAccess=private, SetAccess=private) + source + x + end + methods + function o=cacher(source), o.source=source; o.x=head(source); end + function x=head(o), x=o.x; end + function s=tostring(o), s=['cache(',tostring(o.source),')']; end + function z=elsize(o), z=size(o.x); end + function o=next(o) + o.source=next(o.source); + if ~isempty(o.source), o.x=head(o.source); else o=o.source; end + end + end +end
--- a/sequences/+seq/concat.m Mon Jan 21 11:01:45 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -% seq.concat.make - Concatenate sequences -% -% seq.concat.make :: -% seq(seq(A)) ~ 'sequence of sequences' -% -> seq(A) ~ 'resultant sequence'. -% -% concat :: -% {[N]->seq(A)} ~ 'cell array of N sequences', -% -> seq(A) ~ 'resultant sequence'. -classdef concat < seq - properties (GetAccess=private, SetAccess=private) - current - sources - end - methods (Static) - function o=make(sources) - sources=dropwhile(@isempty,sources); - if isempty(sources), o=nil; - else o=seq.concat(sources); - end - end - end - methods - function o=concat(sources), [o.current,o.sources]=decons(sources); end - function x=head(o), x=head(o.current); end - function s=elsize(o), s=elsize(o.current); end - function s=tostring(o), s=sprintf('concat(%s,...)',tostring(o.current)); end - function o=next(o), - o.current=next(o.current); - if isempty(o.current), o=next_source(o); end - end - - function o=next_source(o) - while isempty(o.current) - if isempty(o.sources), o=nil; break; end - o.current=head(o.sources); - o.sources=next(o.sources); - end - end - end -end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sequences/+seq/concatenator.m Thu Jan 24 14:51:23 2013 +0000 @@ -0,0 +1,41 @@ +% seq.concatenator.make - Concatenate sequences +% +% seq.concatenator.make :: +% seq(seq(A)) ~ 'sequence of sequences' +% -> seq(A) ~ 'resultant sequence'. +% +% concatenator :: +% {[N]->seq(A)} ~ 'cell array of N sequences', +% -> seq(A) ~ 'resultant sequence'. +classdef concatenator < seq + properties (GetAccess=private, SetAccess=private) + current + sources + end + methods (Static) + function o=make(sources) + sources=dropwhile(@isempty,sources); + if isempty(sources), o=nil; + else o=seq.concatenator(sources); + end + end + end + methods + function o=concatenator(sources), [o.current,o.sources]=decons(sources); end + function x=head(o), x=head(o.current); end + function s=elsize(o), s=elsize(o.current); end + function s=tostring(o), s=sprintf('concat(%s,...)',tostring(o.current)); end + function o=next(o), + o.current=next(o.current); + if isempty(o.current), o=next_source(o); end + end + + function o=next_source(o) + while isempty(o.current) + if isempty(o.sources), o=nil; break; end + o.current=head(o.sources); + o.sources=next(o.sources); + end + end + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sequences/+seq/condtaker.m Thu Jan 24 14:51:23 2013 +0000 @@ -0,0 +1,36 @@ +% condtaker - Take elements of seq while a condition is met. +% +% condtaker :: (A->bool), seq(A) -> seq(A). +classdef condtaker < seq + properties (GetAccess=private, SetAccess=private) + source + f + x + end + methods (Static) + function o=make(f,source) + if f(head(source)), o=seq.condtaker(f,source); + else o=nil; + end + end + end + methods + function o=condtaker(f,source) + o.source=source; + o.f=f; + o.x=head(source); + end + + function z=elsize(o), z=size(o.x); end + function s=tostring(o), s=sprintf('takewhile(%s,%s)',tostring(o.f),tostring(o.source)); end + function x=head(o), x=o.x; end + function o=next(o) + o.source=next(o.source); + if isempty(o.source), o=o.source; + else + o.x=head(o.source); + if ~o.f(o.x), o=nil; end + end + end + end +end
--- a/sequences/+seq/cycle.m Mon Jan 21 11:01:45 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -% cycle - cycles through input sequence repeatedly -% -% cycle :: seq(A) -> seq(A). -classdef cycle < seq - properties (GetAccess=private, SetAccess=private) - source - orig - end - methods - function o=cycle(source) - o.orig=source; - o.source=source; - end - - function z=elsize(o), z=elsize(o.source); end - function s=tostring(o), s=sprintf('cycle(%s)',tostring(o.source)); end - function x=head(o), x=head(o.source); end - function o=next(o), - o.source=next(o.source); - if isempty(o.source), o.source=o.orig; end - end - end -end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sequences/+seq/cycler.m Thu Jan 24 14:51:23 2013 +0000 @@ -0,0 +1,23 @@ +% cycler - cycles through input sequence repeatedly +% +% cycler :: seq(A) -> seq(A). +classdef cycler < seq + properties (GetAccess=private, SetAccess=private) + source + orig + end + methods + function o=cycler(source) + o.orig=source; + o.source=source; + end + + function z=elsize(o), z=elsize(o.source); end + function s=tostring(o), s=sprintf('cycle(%s)',tostring(o.source)); end + function x=head(o), x=head(o.source); end + function o=next(o), + o.source=next(o.source); + if isempty(o.source), o.source=o.orig; end + end + end +end
--- a/sequences/+seq/map.m Mon Jan 21 11:01:45 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -% map - seq where values is a stateless function of another sequence -% -% map :: (A->B), seq(A) -> seq(B). -classdef map < seq - properties (GetAccess=public, SetAccess=private) - fn - source - end - methods - function d=map(fn,source,varargin) - d.fn=fn; - d.source=source; - end - - function s=tostring(d), s=sprintf('%s >> %s',tostring(d.source),tostring(d.fn)); end; - function x=head(d), x=d.fn(head(d.source)); end - function s=elsize(d), s=size(head(d)); end - function d=next(d), d.source=next(d.source); if isempty(d.source), d=nil; end; end - end -end
--- a/sequences/+seq/mapaccum.m Mon Jan 21 11:01:45 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -% mapaccum - sequences where values are a stateful function of another sequence -% -% mapaccum :: (A,S->B,S), S, seq(A) -> seq(B). -classdef mapaccum < seq - properties (GetAccess=private, SetAccess=private) - sfn - source - state - x - end - methods - function d=mapaccum(sfn,state,source) - d.sfn=sfn; % function to apply - d.source=source; - [d.x,d.state]=d.sfn(head(source),state); - end - - function s=elsize(d), s=size(d.x); end - function s=tostring(d), s=sprintf('%s >> [%s]',tostring(d.source),tostring(d.sfn)); end - function x=head(d), x=d.x; end - function d=next(d), - d.source=next(d.source); - if ~isempty(d.source) - [d.x,d.state]=d.sfn(head(d.source),d.state); - else - d=nil; - end - end - end -end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sequences/+seq/mapper.m Thu Jan 24 14:51:23 2013 +0000 @@ -0,0 +1,20 @@ +% mapper - seq where values is a stateless function of another sequence +% +% mapper :: (A->B), seq(A) -> seq(B). +classdef mapper < seq + properties (GetAccess=public, SetAccess=private) + fn + source + end + methods + function d=mapper(fn,source,varargin) + d.fn=fn; + d.source=source; + end + + function s=tostring(d), s=sprintf('%s >> %s',tostring(d.source),tostring(d.fn)); end; + function x=head(d), x=d.fn(head(d.source)); end + function s=elsize(d), s=size(head(d)); end + function d=next(d), d.source=next(d.source); if isempty(d.source), d=nil; end; end + end +end
--- a/sequences/+seq/merge.m Mon Jan 21 11:01:45 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -% merge - Combine several seq sources using a given function -% -% merge :: -% ( (A1,...,An)->natural ~ chooser function, -% n:natural ~ number of sources to combine, -% seq A1,...,seq An ~ n seq sources, -% ... ~ options -% ) -> seq B -classdef merge < seq - properties (GetAccess=private, SetAccess=private) - fn - sources - hd - end - methods - function d=merge(c,sources,varargin) - d.fn=c; - d.hd=[]; - d.sources=sources; - end - - - function x=head(d), x=d.hd; end - function d=next(d) - data=cellmap(@head,d.sources); - if isempty(data), d=nil - else - k=d.fn(data); - d.hd=data{k}; - nk=next(d.sources{k}); - if isempty(nk), d.sources(k)=[]; - else d.sources{k}=nk; end - end - end - - function z=elsize(d), z=size(d.hd); end - function s=tostring(d) - s=sprintf('{ %s } >> merge(%s)',catsep(',',cellmap(@tostring,d.sources)),tostring(d.fn)); - end - end -end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sequences/+seq/merger.m Thu Jan 24 14:51:23 2013 +0000 @@ -0,0 +1,41 @@ +% merger - Combine several seq sources using a given function +% +% merger :: +% ( (A1,...,An)->natural ~ chooser function, +% n:natural ~ number of sources to combine, +% seq A1,...,seq An ~ n seq sources, +% ... ~ options +% ) -> seq B +classdef merger < seq + properties (GetAccess=private, SetAccess=private) + fn + sources + hd + end + methods + function d=merger(c,sources,varargin) + d.fn=c; + d.hd=[]; + d.sources=sources; + end + + + function x=head(d), x=d.hd; end + function d=next(d) + data=cellmap(@head,d.sources); + if isempty(data), d=nil + else + k=d.fn(data); + d.hd=data{k}; + nk=next(d.sources{k}); + if isempty(nk), d.sources(k)=[]; + else d.sources{k}=nk; end + end + end + + function z=elsize(d), z=size(d.hd); end + function s=tostring(d) + s=sprintf('{ %s } >> merge(%s)',catsep(',',cellmap(@tostring,d.sources)),tostring(d.fn)); + end + end +end
--- a/sequences/+seq/resize.m Mon Jan 21 11:01:45 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -% resize - sequence with overridden reported element size -% -% resize :: Size:[[1,E]], seq([_->A]) -> seq([Size->A]). -classdef resize < seq - properties (GetAccess=private, SetAccess=private) - source - newsize - check - end - methods - function o=resize(newsize,source,check) - if ~size_match(elsize(source),newsize), - error('seq.resize: size mismatch'); - end - if nargin<3, check=0; end - o.source=source; - o.newsize=newsize; - o.check=check; - end - - function x=head(a), x=head(a.source); if a.check, size_check(a.newsize,size(x)); end; end - function d=next(d), d.source=next(d.source); if isempty(d.source), d=nil; end; end - function s=elsize(a), s=a.newsize; end - function s=tostring(a), s=tostring(a.source); end - end -end - -function b=size_match(s1,s2) - b=all((s1==s2) | isnan(s1) | isnan(s2)); -end - -function b=size_check(spec,size) - if ~all((spec==size) | isnan(spec)) - error('seq.resize: element size does not match specification'); - end -end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sequences/+seq/resizer.m Thu Jan 24 14:51:23 2013 +0000 @@ -0,0 +1,36 @@ +% resizer - sequence with overridden reported element size +% +% resizer :: Size:[[1,E]], seq([_->A]) -> seq([Size->A]). +classdef resizer < seq + properties (GetAccess=private, SetAccess=private) + source + newsize + check + end + methods + function o=resizer(newsize,source,check) + if ~size_match(elsize(source),newsize), + error('seq.resizer: size mismatch'); + end + if nargin<3, check=0; end + o.source=source; + o.newsize=newsize; + o.check=check; + end + + function x=head(a), x=head(a.source); if a.check, size_check(a.newsize,size(x)); end; end + function d=next(d), d.source=next(d.source); if isempty(d.source), d=nil; end; end + function s=elsize(a), s=a.newsize; end + function s=tostring(a), s=tostring(a.source); end + end +end + +function b=size_match(s1,s2) + b=all((s1==s2) | isnan(s1) | isnan(s2)); +end + +function b=size_check(spec,size) + if ~all((spec==size) | isnan(spec)) + error('seq.resizer: element size does not match specification'); + end +end
--- a/sequences/+seq/scanl.m Mon Jan 21 11:01:45 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -% scanl - sequence of values accumulated by function passing over sequence -% -% This works like scanl in a functional language (see eg, Haskell) -% -% scanl :: -% (S,A)->S) ~ function to update output given new input, -% S ~ initial state, -% seq(A), ~ source seq -%-> seq(S). -classdef scanl < seq - properties (GetAccess=private, SetAccess=private) - scanfn - source - x - end - methods - function d=scanl(f,s0,source) - d.scanfn=f; % function to apply - d.x=d.scanfn(s0,head(source)); - d.source=next(source); - end - - function s=tostring(d), s=sprintf('%s >> scan(%s)',tostring(d.source),tostring(d.scanfn)); end - function z=elsize(d), z=size(d.x); end; - function x=head(d), x=d.x; end - function d=next(d), - if isempty(d.source), d=d.source; return; end - d.x=d.scanfn(d.x,head(d.source)); - d.source=next(d.source); - end - end -end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sequences/+seq/scanner.m Thu Jan 24 14:51:23 2013 +0000 @@ -0,0 +1,32 @@ +% scanner - sequence of values accumulated by function passing over sequence +% +% This works like scanl in a functional language (see eg, Haskell) +% +% scanner :: +% (S,A)->S) ~ function to update output given new input, +% S ~ initial state, +% seq(A), ~ source seq +%-> seq(S). +classdef scanner < seq + properties (GetAccess=private, SetAccess=private) + scanfn + source + x + end + methods + function d=scanner(f,s0,source) + d.scanfn=f; % function to apply + d.x=d.scanfn(s0,head(source)); + d.source=next(source); + end + + function s=tostring(d), s=sprintf('%s >> scan(%s)',tostring(d.source),tostring(d.scanfn)); end + function z=elsize(d), z=size(d.x); end; + function x=head(d), x=d.x; end + function d=next(d), + if isempty(d.source), d=d.source; return; end + d.x=d.scanfn(d.x,head(d.source)); + d.source=next(d.source); + end + end +end
--- a/sequences/+seq/select.m Mon Jan 21 11:01:45 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -% select - Use boolean function to keep only matching elements from sequence -% -% select :: (A->bool), seq(A) -> seq(A). -classdef select < seq - properties (GetAccess=private, SetAccess=private) - fn % :: A->bool - source % :: seq(A) - x % :: A - end - methods (Static) - function o=make(fn,source) - source=dropwhile(inverse(fn),source); - if isempty(source), o=nil; else o=seq.select(fn,source); - end - end - methods - function d=select(fn,source) - d.fn=fn; - d.x=head(source); - d.source=source; - end - - function z=elsize(o), z=elsize(d.x); end - function s=tostring(o), s=sprintf('%s >> %s?',tostring(o.source),tostring(o.fn)); end - function x=head(d), x=d.x; end - function o=next(o) - while 1 - o.source=next(o.source); - if isempty(o.source), o=nil; return; end - o.x=head(o.source); - if o.fn(o.x), break; end - end - end - end -end - -function g=inverse(f), g=@(x)~f(x); end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sequences/+seq/selector.m Thu Jan 24 14:51:23 2013 +0000 @@ -0,0 +1,37 @@ +% selector - Use boolean function to keep only matching elements from sequence +% +% selector :: (A->bool), seq(A) -> seq(A). +classdef selector < seq + properties (GetAccess=private, SetAccess=private) + fn % :: A->bool + source % :: seq(A) + x % :: A + end + methods (Static) + function o=make(fn,source) + source=dropwhile(inverse(fn),source); + if isempty(source), o=nil; else o=seq.selector(fn,source); + end + end + methods + function d=selector(fn,source) + d.fn=fn; + d.x=head(source); + d.source=source; + end + + function z=elsize(o), z=elsize(d.x); end + function s=tostring(o), s=sprintf('%s >> %s?',tostring(o.source),tostring(o.fn)); end + function x=head(d), x=d.x; end + function o=next(o) + while 1 + o.source=next(o.source); + if isempty(o.source), o=nil; return; end + o.x=head(o.source); + if o.fn(o.x), break; end + end + end + end +end + +function g=inverse(f), g=@(x)~f(x); end
--- a/sequences/+seq/skin.m Mon Jan 21 11:01:45 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -% skin - Give a sequence arbitrary string represention -% -% skin :: seq(A), (seq(A)->string) -> seq(A). -classdef skin < seq - properties (GetAccess=private, SetAccess=private) - source - stringfn - end - methods - function o=skin(source,stringfn) - o.source=source; o.stringfn=stringfn; - end - - function x=head(a), x=head(a.source); end - function d=next(d), d.source=next(d.source); if isempty(d.source), d=nil; end; end - function s=elsize(a), s=elsize(a.source); end - function s=tostring(a), s=a.stringfn(a); end - end -end -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sequences/+seq/skinner.m Thu Jan 24 14:51:23 2013 +0000 @@ -0,0 +1,20 @@ +% skinner - Give a sequence arbitrary string represention +% +% skinner :: seq(A), (seq(A)->string) -> seq(A). +classdef skinner < seq + properties (GetAccess=private, SetAccess=private) + source + stringfn + end + methods + function o=skinner(source,stringfn) + o.source=source; o.stringfn=stringfn; + end + + function x=head(a), x=head(a.source); end + function d=next(d), d.source=next(d.source); if isempty(d.source), d=nil; end; end + function s=elsize(a), s=elsize(a.source); end + function s=tostring(a), s=a.stringfn(a); end + end +end +
--- a/sequences/+seq/slices.m Mon Jan 21 11:01:45 2013 +0000 +++ b/sequences/+seq/slices.m Thu Jan 24 14:51:23 2013 +0000 @@ -1,23 +1,8 @@ % slices - sequence obtained from slices of an array -% -% slices :: -% [[Size,M]->A] ~'array to slices', -% -> seq([[Size]->A]). -% -% slices :: -% [Size->A] ~'array to slices', -% D:natural ~'dimension of desired values' -% -> seq([Size:[[1,D]]->A]). -% -% If 2nd parameter not given, the array is sliced along it's -% last non-singleton dimension, so the element size is the size -% after this dimension has been removed. If given, the dimension -% parameter cannot be smaller than the number of non-singleton -% dimensions in the input. classdef slices < seq properties (GetAccess=private, SetAccess=immutable) - slice % natural -> [[N]] + slice % natural -> [Size1->A] elsz % [[1,E]] length % natural dim @@ -28,19 +13,19 @@ methods function d=slices(x,dim) sz=strip1(size(x)); - if nargin<2, dim=length(sz)-1; end - if dim<length(sz)-1, error('Cannot slice along inner dimensions'); end + maxdim=length(sz); + if nargin<2, dim=maxdim; end - d.elsz=sz(1:dim); - d.slice=slicer(x,dim+1); - d.length=size(x,dim+1); + d.elsz=arrset(sz,dim,1); + d.slice=slicer(x,dim,maxdim); + d.length=size(x,dim); d.index=1; d.dim=dim; end function s=elsize(o), s=tosize(o.elsz); end function s=tostring(o), - s=sprintf('slices(x:[%s],%d)@%d',mat2str([o.elsz,o.length]),o.dim,o.index); + s=sprintf('slices(<[%s]>,%d)@%d',mat2str(arrset(o.elsz,o.dim,o.length)),o.dim,o.index); end function x=head(o), x=o.slice(o.index); end function o=next(o) @@ -49,13 +34,31 @@ end end -function f=slicer(x,dim) - switch dim - case 1, f=@(i)x(i); - case 2, f=@(i)x(:,i); - case 3, f=@(i)x(:,:,i); - otherwise - colons=repmat({':'},1,dim-1); - f=@(i)x(colons{:},i); +function f=slicer(x,dim,maxdim) + if maxdim>3, + if dim>=maxdim, f=outslicer(x,dim); + else f=inslicer(x,dim,maxdim); + end + else + switch dim + case 1, f=cellget({@(i)x(i), @(i)x(i,:), @(i)x(i,:,:)}, maxdim); + case 2, if maxdim==3, f=@(i)x(:,i,:); else f=@(i)x(:,i); end + case 3, f=@(i)x(:,:,i); + otherwise, f=outslicer(x,dim); + end end end + +function f=outslicer(x,dim,maxdim) + c1=repmat({':'},1,dim-1); + f=@(i)x(c1{:},i); +end + +% for slicing along inner dimensions - need trailing colons to catch remaining +% dimensions +function f=inslicer(x,dim,maxdim) + c1=repmat({':'},1,dim-1); + c2=repmat({':'},1,maxdim-dim); + f=@(i)x(c1{:},i,c2{:}); +end +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sequences/+seq/stmapper.m Thu Jan 24 14:51:23 2013 +0000 @@ -0,0 +1,30 @@ +% stmapper - stateful mapper +% +% stmapper :: (A,S->B,S), S, seq(A) -> seq(B). +classdef stmapper < seq + properties (GetAccess=private, SetAccess=private) + sfn + source + state + x + end + methods + function d=stmapper(sfn,state,source) + d.sfn=sfn; % function to apply + d.source=source; + [d.x,d.state]=d.sfn(head(source),state); + end + + function s=elsize(d), s=size(d.x); end + function s=tostring(d), s=sprintf('%s >> [%s]',tostring(d.source),tostring(d.sfn)); end + function x=head(d), x=d.x; end + function d=next(d), + d.source=next(d.source); + if ~isempty(d.source) + [d.x,d.state]=d.sfn(head(d.source),d.state); + else + d=nil; + end + end + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sequences/+seq/stzipper.m Thu Jan 24 14:51:23 2013 +0000 @@ -0,0 +1,38 @@ +% stzipper - Combine several seq sources using a stateful function +% +% stzipper :: +% (A(1),...,A(N),S->B,S) ~ 'zipping function', +% S ~ 'initial state', +% {I:[N]->seq(A(I))} ~ 'cell array of N sequences', +% -> seq(B). +classdef stzipper < seq + properties (GetAccess=private, SetAccess=private) + fn + sources + state + x + end + methods + function d=stzipper(fn,state0,sources) + d.fn=fn; + d.sources=sources; + heads=cellmap(@head,sources); + [d.x,d.state]=d.fn(heads{:},state0); + end + + function z=elsize(o), z=size(o.x); end + function x=head(d), x=d.x; end + function d=next(d) + d.sources=cellmap(@next,d.sources); + if any(cell2mat(cellmap(@isempty,d.sources))), d=nil; + else + args=cellmap(@head,d.sources); + [d.x,d.state]=d.fn(args{:},d.state); + end + end + + function s=tostring(d) + s=sprintf('{%s} >> [%s]',catsep(',',cellmap(@tostring,d.sources)),tostring(d.fn)); + end + end +end
--- a/sequences/+seq/subsample.m Mon Jan 21 11:01:45 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -% subsample - keep every N values from a sequence -% -% subsample :: -% natural ~ sample rate, -% seq(A), ~ source seq, -% ... ~ options) -% -> seq(A). -classdef subsample < seq - properties (GetAccess=private, SetAccess=private) - source - n - end - methods - function d=subsample(a,s), d.n=a; d.source=s; end - function s=tostring(d), s=sprintf('%s >> subsample(%d)',tostring(d.source),tostring(d.n)); end - function z=elsize(o), o=size(head(o)); end - function x=head(d), x=head(d.source); end - function o=next(o) - for i=1:o.n - o.source=next(o.source); - if isempty(o.source), o=nil; break; end - end - end - end -end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sequences/+seq/subsampler.m Thu Jan 24 14:51:23 2013 +0000 @@ -0,0 +1,25 @@ +% subsampler - keep every N values from a sequence +% +% subsampler :: +% natural ~ sample rate, +% seq(A), ~ source seq, +% ... ~ options) +% -> seq(A). +classdef subsampler < seq + properties (GetAccess=private, SetAccess=private) + source + n + end + methods + function d=subsampler(a,s), d.n=a; d.source=s; end + function s=tostring(d), s=sprintf('%s >> subsample(%d)',tostring(d.source),tostring(d.n)); end + function z=elsize(o), o=size(head(o)); end + function x=head(d), x=head(d.source); end + function o=next(o) + for i=1:o.n + o.source=next(o.source); + if isempty(o.source), o=nil; break; end + end + end + end +end
--- a/sequences/+seq/take.m Mon Jan 21 11:01:45 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -% TAKE - Take first n alements of sequence then stop -% -% take :: natural, seq(A) -> seq(A). -classdef take < seq - properties (GetAccess=private, SetAccess=private) - source - n - end - methods (Static) - function o=make(n,source) - if n==0 || isempty(source), o=nil; - else o=seq.take(n,source); - end - end - end - methods - function o=take(n,source), o.source=source; o.n=n; end - function z=elsize(o), z=elsize(o.source); end - function s=tostring(o), s=sprintf('take(%d,%s)',o.n,tostring(o.source)); end - function x=head(o), x=head(o.source); end - function o=next(o) - if o.n==1, o=[]; - else - o.source=next(o.source); - if isempty(o), o=o.source; else o.n=o.n-1; end - end - end - end -end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sequences/+seq/taker.m Thu Jan 24 14:51:23 2013 +0000 @@ -0,0 +1,29 @@ +% taker - Take first n alements of sequence then stop +% +% taker :: natural, seq(A) -> seq(A). +classdef taker < seq + properties (GetAccess=private, SetAccess=private) + source + n + end + methods (Static) + function o=make(n,source) + if n==0 || isempty(source), o=nil; + else o=seq.taker(n,source); + end + end + end + methods + function o=taker(n,source), o.source=source; o.n=n; end + function z=elsize(o), z=elsize(o.source); end + function s=tostring(o), s=sprintf('take(%d,%s)',o.n,tostring(o.source)); end + function x=head(o), x=head(o.source); end + function o=next(o) + if o.n==1, o=[]; + else + o.source=next(o.source); + if isempty(o), o=o.source; else o.n=o.n-1; end + end + end + end +end
--- a/sequences/+seq/takewhile.m Mon Jan 21 11:01:45 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -% takewhile - Take elements of seq while a condition is met. -% -% takewhile :: (A->bool), seq(A) -> seq(A). -classdef takewhile < seq - properties (GetAccess=private, SetAccess=private) - source - f - x - end - methods (Static) - function o=make(f,source) - if f(head(source)), o=seq.takewhile(f,source); - else o=nil; - end - end - end - methods - function o=takewhile(f,source) - o.source=source; - o.f=f; - o.x=head(source); - end - - function z=elsize(o), z=size(o.x); end - function s=tostring(o), s=sprintf('takewhile(%s,%s)',tostring(o.f),tostring(o.source)); end - function x=head(o), x=o.x; end - function o=next(o) - o.source=next(o.source); - if isempty(o.source), o=o.source; - else - o.x=head(o.source); - if ~o.f(o.x), o=nil; end - end - end - end -end
--- a/sequences/+seq/window.m Mon Jan 21 11:01:45 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,130 +0,0 @@ -% window - abstract data object for extracting window from another data -% -% window :: -% X:seq([[C,M]]) ~'source signal', -% N:natural ~'window size', -% natural ~'hop size', -% options { -% dim :: natural/ndims(X) ~'dimension to window along (default is last)'; -% wrap:: bool /1 ~ if 1, then source is treated as a contiguous stream in -% the dimth dimension; otherwise, each buffer is windowed -% independently.' -% } -% -> seq([[C,N]]). -classdef window < seq - properties (GetAccess=private, SetAccess=private) - source - hop - length - pos - opts - curr - end - methods (Static) - function d=make(src,span,hop,varargin) - if isempty(src), d=nil; return; end - d=seq.window(src,span,hop,varargin{:}); - end - end - methods - function a=window(src,span,hop,varargin) - if nargin<3, - if nargin<2, span=1; end - hop=span; - end - sz=size(src); - opts=prefs('wrap',1,'dim',length(sz),'strict',1,varargin{:}); - - dim=opts.dim; wrap=opts.wrap; - a.hop=hop; a.span=span; - - % mutable state - a.length=sz(dim); - a.pos = 0; - a.opts =opts; - a.curr =[]; - - % sort out function table - if wrap - ft.headfn=@(a)a.curr; - ft.nextfn=@next_caching; - - [a.curr,src,a.pos,a.length]=itread(dim,span,src,0,a.length); - if size(a.curr,dim)<span, a=[]; return; end; % !! Strict window length? - a.source=src; - a=a@dseq(src,arrset(sz,dim,span),ft); - else - ft.headfn=@(a)extract(head(source(a)),dim,a.pos+[1 span]); - ft.nextfn=@next_seq_nowrap; - a.source=src; - - a=a@dseq(src,arrset(sz,dim,span),ft); - if a.length<span, a=next_seq_nowrap(a); end; - end - - - % optimised next (assumes wrap=1) - function a=next_caching(a) - src=source(a); - if isempty(src) - a=[]; - else - [x,src,a.pos,a.length]=itread(dim,hop,src,a.pos,a.length); - if size(x,dim)<hop, - if opts.strict, - a=[]; % strict window length - else - a.curr=cat(dim,extract(a.curr,dim,[hop+1 span]),x); - a.source=src; - end - else - a.curr=cat(dim,extract(a.curr,dim,[hop+1 span]),x); - a.source=src; - end - end - end - - function a=next_seq_nowrap(a) - a.pos=a.pos+hop; % next window position - while a.pos+span>a.length % next window would overrun - a=next_nc(a); if isempty(a), break; end - a.length=size(source(a),dim); - a.pos=0; - end - end - end - - - % iterative read - read len samples starting at pos in head - % buffer of source. Returns tail source and pos for subsequent - % reads. - function [chunk,source,pos,max]=itread(dim,len,source,pos,max) - if len==0 || isempty(source), chunk=[]; return; end - - chunk=[]; - if pos+len>=max - chunk=extract(head(source),dim,[pos+1 max]); - len=pos+len-max; - source=next(source); - if ~isempty(source), - max=size(source,dim); - while len>=max - chunk=cat(dim,chunk,head(source)); len=len-max; - source=next(source); - if isempty(source), break; end - max=size(source,dim); - end - pos=0; - end - end - if ~isempty(source), - ex=extract(head(source),dim,pos+[1 len]); - if isempty(chunk), chunk=ex; else chunk=cat(dim,chunk,ex); end - pos=pos+len; - end - end - end - - function s=stringfn(a), s=sprintf('%s >> window(%d/%d)',tostring(a.source),a.span,a.hop); end - end -end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sequences/+seq/windower.m Thu Jan 24 14:51:23 2013 +0000 @@ -0,0 +1,134 @@ +% windower - sequence for rebuffering a sequence +% +% windower :: +% X:seq([[C,M]]) ~'source signal', +% N:natural ~'window size', +% natural ~'hop size', +% options { +% dim :: natural/ndims(X) ~'dimension to window along (default is last)'; +% wrap:: bool /1 ~ if 1, then source is treated as a contiguous stream in +% the dimth dimension; otherwise, each buffer is windowed +% independently.' +% } +% -> seq([[C,N]]). +classdef windower < seq + properties (GetAccess=private, SetAccess=private) + source + hop + length + pos + opts + curr + span + bufsize + headfn + nextfn + end + methods (Static) + function d=make(src,varargin) + if isempty(src), d=nil; return; end + d=seq.windower(src,varargin{:}); + end + end + methods + function x=head(a), x=a.headfn(a); end + function b=next(a), b=a.nextfn(a); end + function z=elsize(a), z=a.bufsize; end + function s=tostring(a), s=sprintf('%s >> window(%d/%d)',tostring(a.source),a.span,a.hop); end + function a=windower(src,span,hop,varargin) + if nargin<3, + if nargin<2, span=1; end + hop=span; + end + sz=size(src); + opts=prefs('wrap',1,'dim',length(sz),'strict',1,varargin{:}); + + dim=opts.dim; wrap=opts.wrap; + a.hop=hop; a.span=span; + + % mutable state + a.length=sz(dim); + a.pos = 0; + a.opts =opts; + a.curr =[]; + + % sort out function table + if wrap + a.headfn=@(a)a.curr; + a.nextfn=@next_caching; + + [a.curr,src,a.pos,a.length]=itread(dim,span,src,0,a.length); + if size(a.curr,dim)<span, a=[]; return; end; % !! Strict window length? + a.source=src; + a.bufsize=arrset(sz,dim,span); + else + a.headfn=@(a)extract(head(a.source),dim,a.pos+[1 span]); + a.nextfn=@next_seq_nowrap; + a.source=src; + a.bufsize=arrset(sz,dim,span); + if a.length<span, a=next_seq_nowrap(a); end; + end + + + % optimised next (assumes wrap=1) + function a=next_caching(a) + src=a.source; + if isempty(src) + a=[]; + else + [x,src,a.pos,a.length]=itread(dim,hop,src,a.pos,a.length); + if size(x,dim)<hop, + if opts.strict, + a=[]; % strict window length + else + a.curr=cat(dim,extract(a.curr,dim,[hop+1 span]),x); + a.source=src; + end + else + a.curr=cat(dim,extract(a.curr,dim,[hop+1 span]),x); + a.source=src; + end + end + end + + function a=next_seq_nowrap(a) + a.pos=a.pos+hop; % next window position + while a.pos+span>a.length % next window would overrun + a.source=next(a.source); + if isempty(a.source), a=[]; break; end + a.length=size(a.source,dim); + a.pos=0; + end + end + end + end +end + +% iterative read - read len samples starting at pos in head +% buffer of source. Returns tail source and pos for subsequent +% reads. +function [chunk,source,pos,max]=itread(dim,len,source,pos,max) + if len==0 || isempty(source), chunk=[]; return; end + + chunk=[]; + if pos+len>=max + chunk=extract(head(source),dim,[pos+1 max]); + len=pos+len-max; + source=next(source); + if ~isempty(source), + max=size(source,dim); + while len>=max + chunk=cat(dim,chunk,head(source)); len=len-max; + source=next(source); + if isempty(source), break; end + max=size(source,dim); + end + pos=0; + end + end + if ~isempty(source), + ex=extract(head(source),dim,pos+[1 len]); + if isempty(chunk), chunk=ex; else chunk=cat(dim,chunk,ex); end + pos=pos+len; + end +end
--- a/sequences/+seq/zipaccum.m Mon Jan 21 11:01:45 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -% zipaccum - Combine several seq sources using a stateful function -% -% zipaccum :: -% (A(1),...,A(N),S->B,S) ~ 'zipping function', -% S ~ 'initial state', -% {I:[N]->seq(A(I))} ~ 'cell array of N sequences', -% -> seq(B). -classdef zipaccum < seq - properties (GetAccess=private, SetAccess=private) - fn - sources - state - x - end - methods - function d=zipaccum(fn,state0,sources) - d.fn=fn; - d.sources=sources; - heads=cellmap(@head,sources); - [d.x,d.state]=d.fn(heads{:},state0); - end - - function z=elsize(o), z=size(o.x); end - function x=head(d), x=d.x; end - function d=next(d) - d.sources=cellmap(@next,d.sources); - if any(cell2mat(cellmap(@isempty,d.sources))), d=nil; - else - args=cellmap(@head,d.sources); - [d.x,d.state]=d.fn(args{:},d.state); - end - end - - function s=tostring(d) - s=sprintf('{%s} >> [%s]',catsep(',',cellmap(@tostring,d.sources)),tostring(d.fn)); - end - end -end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sequences/+seq/zipper.m Thu Jan 24 14:51:23 2013 +0000 @@ -0,0 +1,35 @@ +% zipper - Combine several seq sources using a given function +% +% zipper :: +% (A(1),...,A(N)->B) ~ 'zipping function', +% {I:[N]->seq(A(I))} ~ 'cell array of N sequences', +% -> seq(B). +classdef zipper < seq + properties (GetAccess=private, SetAccess=private) + fn + sources + end + + methods + function d=zipper(fn,sources) + d.fn=fn; + d.sources=sources; + end + + function s=elsize(d), s=size(head(d)); end + function x=head(d) + args=cellmap(@head,d.sources); + x=d.fn(args{:}); + end + + function d=next(d) + d.sources=cellmap(@next,d.sources); + if any(cell2mat(cellmap(@isempty,d.sources))), d=nil; end + end + + function s=tostring(d) + s=sprintf('{%s} >> %s',catsep(',',cellmap(@tostring,d.sources)),tostring(d.fn)); + end + + end +end
--- a/sequences/+seq/zipwith.m Mon Jan 21 11:01:45 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -% zipwith - Combine several seq sources using a given function -% -% zipwith :: -% (A(1),...,A(N)->B) ~ 'zipping function', -% {I:[N]->seq(A(I))} ~ 'cell array of N sequences', -% -> seq(B). -classdef zipwith < seq - properties (GetAccess=private, SetAccess=private) - fn - sources - end - - methods - function d=zipwith(fn,sources) - d.fn=fn; - d.sources=sources; - end - - function s=elsize(d), s=size(head(d)); end - function x=head(d) - args=cellmap(@head,d.sources); - x=d.fn(args{:}); - end - - function d=next(d) - d.sources=cellmap(@next,d.sources); - if any(cell2mat(cellmap(@isempty,d.sources))), d=nil; end - end - - function s=tostring(d) - s=sprintf('{%s} >> %s',catsep(',',cellmap(@tostring,d.sources)),tostring(d.fn)); - end - - end -end
--- a/sequences/@seq/seq.m Mon Jan 21 11:01:45 2013 +0000 +++ b/sequences/@seq/seq.m Thu Jan 24 14:51:23 2013 +0000 @@ -1,8 +1,8 @@ % seq - Base class for sequences classdef seq - properties (Constant, GetAccess=public) - NIL = seq.nil - end +% properties (Constant, GetAccess=public) +% NIL = seq.nil +% end methods (Abstract) x=head(a) % seq(A) -> A. @@ -51,17 +51,16 @@ end methods - % decons - head and tail of sequence - % decons :: seq(A) -> A, seq(A). function [x,b]=decons(a) + % decons - head and tail of sequence + % decons :: seq(A) -> A, seq(A). x=head(a); b=next(a); end - % last - get the last array in a sequence (there must be at least one element) - % - % last :: seq(A) -> A. function z=last(y) + % last - get the last array in a sequence (there must be at least one element) + % last :: seq(A) -> A. while ~isempty(y), x=y; y=next(x); end z=head(x); end @@ -70,72 +69,80 @@ % ------------- WRAPPERS FOR OTHER SEQ CLASSES --------------------------- - function y=take(n,x), y=seq.take.make(n,x); end; + function y=take(n,x), y=seq.taker.make(n,x); end; function y=takewhile(f,x), y=seq.takewhile.make(f,x); end - % drop - Drop the first n alements of sequence - % - % drop :: natural, seq A -> seq A function s=drop(n,s), + % drop - Drop the first n alements of sequence + % drop :: natural, seq(A) -> seq(A) for i=1:n if ~isempty(s), s=next(s); end; end end - % dropwhile - Drop elements of sequence that satisfy condition - % - % drop :: (A->bool), seq A -> seq A function s=dropwhile(f,s) + % dropwhile - Drop elements of sequence that satisfy condition + % drop :: (A->bool), seq(A) -> seq(A) while ~isempty(s) && f(head(s)), s=next(s); end end - % nth1 - Get nth element of a sequence starting at 1 - % - % nth1 :: natural, seq X -> X, seq X ~'tail of sequence'. function [x,tail]=nth1(n,X) + % nth1 - Get nth element of a sequence starting at 1 + % nth1 :: natural, seq(X) -> X, seq(X) ~'tail of sequence'. z=drop(n-1,X); x=head(z); if nargout>=2, tail=next(z); end end + function Y=once(X), Y=cons(head(X),[]); end % once - equivalent to take(1,...) + % once :: seq(A) -> seq(A). + + function x=map(fn,y) + % map - seq where values is a stateless function of another sequence % - % once :: seq A -> seq A. - function Y=once(X), Y=cons(head(X),[]); end + % map :: (A->B), seq(A) -> seq(B). + if isempty(y), x=nil; else x=seq.mapper(fn,y); end; + end - function x=map(fn,y), if isempty(y), x=nil; else x=seq.map(fn,y); end; end - function y=cache(x), if isempty(x), y=nil; else y=seq.cache(x); end; end - function x=select(fn,y), x=seq.select.make(fn,y); end - function y=buffer(x,varargin), y=seq.buffer.make(x,varargin{:}); end + function x=select(fn,y) + % select - Use boolean function to keep only matching elements from sequence + % + % select :: (A->bool), seq(A) -> seq(A). + x=seq.selector.make(fn,y); + end + + function y=cache(x), if isempty(x), y=nil; else y=seq.cacher(x); end; end + function y=buffer(x,varargin), y=seq.bufferer.make(x,varargin{:}); end function x=mapaccum(fn,s0,y) if iscell(y), x=cmapaccum(fn,s0,y); elseif isempty(y), x=nil; - else x=seq.mapaccum(fn,s0,y); + else x=seq.stmapper(fn,s0,y); end end - % scanl - scanl combinator for sequences - % - % This function applies an associative operator to a list of arguments, - % starting from the left using the given starting element. - % - % scanl :: - % (X,Y->X) ~'associative binary operator', - % X ~'initial element', - % seq Y ~'a sequence' - % -> seq X. - function x=scanl(fn,e,y,varargin), + function x=scanl(fn,e,y,varargin) + % scanl - scanl combinator for sequences + % + % This function applies an associative operator to a list of arguments, + % starting from the left using the given starting element. + % + % scanl :: + % (X,Y->X) ~'associative binary operator', + % X ~'initial element', + % seq(Y) ~'a sequence' + % -> seq(X). if iscell(y), x=cscanl(fn,e,y,varargin{:}); elseif isempty(y), x=nil; - else x=seq.scanl(fn,e,y,varargin{:}); + else x=seq.scanner(fn,e,y,varargin{:}); end end % concat - Concatenate sequences % % concat :: seq(seq(A)) -> seq(A). - function y=concat(x), y=seq.concat.make(x); end + function y=concat(x), y=seq.concatenator.make(x); end % append - Append one or more sequences % @@ -146,55 +153,72 @@ if isempty(x) if isempty(y), z=nil; else z=y; end else - if isempty(y), z=x; else z=seq.concat(cons(x,cons(y,nil))); end + if isempty(y), z=x; else z=seq.concatenator(cons(x,cons(y,nil))); end end end - % cycle - cycles through input sequence repeatedly - % - % cycle :: seq(A) -> seq(A). function y=cycle(x) + % cycle - cycles through input sequence repeatedly + % + % cycle :: seq(A) -> seq(A). if isempty(x), error('seq: cannot cycle empty sequence'); end; - y=seq.cycle(x); + y=seq.cycler(x); end - function y=bindcat(x,f), y=seq.bindcat(x,f); end - % bindcat :: seq(A), (A->seq(A)) -> seq(A). + function y=bindcat(x,f) + % bindcat - sort of monadic bind for sequences. + % + % bindcat :: + % seq(A) ~ 'the first sequence', + % (A->seq(A)) ~ 'function to return second sequence given last element of first' + % -> seq(A) ~ 'resultant sequence'. + % + % The resulting sequence consists of the entire sequence represented by the + % first parameter, followed by the sequence obtained by applying the second + % parameter to the last element of the first sequence. + % + % Example: + % + % gather(2,bindcat(cellseq({1,2,3,4}),@(x)take(head(x),0))) + % + % ans = 1 2 3 4 0 0 0 0 + y=seq.binder(x,f); + end - function y=subsample(n,x), if isempty(x), y=nil; else y=seq.subsample(n,x); end; end + function y=subsample(n,x), if isempty(x), y=nil; else y=seq.subsampler(n,x); end; end function x=zip(varargin) % zip - combine several sequences into one % % zip :: seq(A), seq(B), ... -> seq(cell {A,B,...}). - x=seq.zipwith(@tuple,varargin); + x=seq.zipper(@tuple,varargin); function z=rtuple(varargin), z=varargin; end end - % zipwith - apply function to several sequences - % - % zipwith :: - % (A,B,...->X), - % seq A, seq B, ... - % -> seq X. function x=zipwith(fn,varargin), + % zipwith - apply function to several sequences + % + % zipwith :: + % (A,B,...->X), + % seq(A), seq(B), ... + % -> seq(X). if any(cell2mat(cellmap(@isempty,varargin))), x=nil; - else x=seq.zipwith(fn,varargin); + else x=seq.zipper(fn,varargin); end end - % zipaccum - apply stateful function to several sequences - % - % zipaccum :: - % (A,B,...,S->X,S), - % S, - % seq(A), seq(B), ... - % -> seq(X). function x=zipaccum(fn,s0,varargin), + % zipaccum - apply stateful function to several sequences + % + % zipaccum :: + % (A,B,...,S->X,S), + % S, + % seq(A), seq(B), ... + % -> seq(X). if isseq(s0) && any(map(@iscell,varargin)) % catch dispatching errors z=czipcaccum(fn,s0,varargin{:}); elseif any(cell2mat(cellmap(@isempty,varargin))), x=nil; - else x=seq.zipaccum(fn,s0,varargin); + else x=seq.stzipper(fn,s0,varargin); end end @@ -216,7 +240,7 @@ function y=merge(f,varargin), if all(cell2mat(cellmap(@isempty,varargin))), y=nil; - else y=seq.merge(f,varargin); end + else y=seq.merger(f,varargin); end end @@ -224,7 +248,7 @@ % BINOP - Binary operation % - % binop :: seq A, seq B, (A,B->C), string -> seq C. + % binop :: seq(A), seq(B), (A,B->C), string -> seq(C). % % Three cases % A is seq, B is an array @@ -311,13 +335,13 @@ end function y=paren(a,S) - % paren - Map application of subsref with parentheses to sequence - % - % paren :: seq A, subs -> seq B :- (subsref :: A, subs -> B). + % paren - Map application of subsref with parentheses to sequence + % + % paren :: seq(A), subs -> seq(B) :- (subsref :: A, subs -> B). - % NOTE TO SELF: it would be good to work out the size of the - % array that will result when the function is evaluated, to - % save map evaluating it once on construction. + % NOTE TO SELF: it would be good to work out the size of the + % array that will result when the function is evaluated, to + % save map evaluating it once on construction. y=map(@(z)subsref(z,S),a); % 'charfn',@(o)charfn(tostring(S.subs{:}),o)); function s=charfn(argstr,o)
--- a/sequences/@seq/skin.m Mon Jan 21 11:01:45 2013 +0000 +++ b/sequences/@seq/skin.m Thu Jan 24 14:51:23 2013 +0000 @@ -2,5 +2,5 @@ % % skin :: seq(A), (seq(A)->string) -> seq(A). function y=skin(s,strfn), - if isempty(s), y=nil; else y=seq.skin(s,strfn); end + if isempty(s), y=nil; else y=seq.skinner(s,strfn); end end
--- a/sequences/@seq/window.m Mon Jan 21 11:01:45 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -% window - Window a sequnce of arrays in a given dimension -% -% window :: seq [[N,M]] -> seq [[N]]. -% window :: seq [[N,M]], L:natural -> seq [[N,L]]. -% window :: seq [[N,M]], L:natural, natural ~'hop size' -> seq [[N,L]]. -% -% This is just short for windowdata(...) -% Possible optimisation: -% when the span and hop are much less than the input buffer size -% and the source data does not have an efficient extract method, -% then it is worth caching the source data, ie window(cache(x),...) -function Y=window(X,varargin), Y=seq.window.make(X,varargin{:});
--- a/sequences/@seq/window_ns.m Mon Jan 21 11:01:45 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -function Y=window_ns(X,W,H), -% window_ns - Window a sequnce of arrays in a given dimension (no strict size) -% -% window_ns :: seq [[N,M]] -> seq [[N]]. -% window_ns :: seq [[N,M]], L:natural -> seq [[N,L]]. -% window_ns :: seq [[N,M]], L:natural, natural ~'hop size' -> seq [[N,L]]. - -if nargin<2, W=1; H=1; -elseif nargin<3, H=W; -end - -Y=seq.window.make(X,W,H,'strict',0);
--- a/sequences/concatseqs.m Mon Jan 21 11:01:45 2013 +0000 +++ b/sequences/concatseqs.m Thu Jan 24 14:51:23 2013 +0000 @@ -5,5 +5,5 @@ % -> seq(A) ~ 'resultant sequence'. function o=concat(sources) if iscell(sources), sources=cellseq(sources); end - o=seq.concat.make(cellseq(sources)); + o=seq.concatenator.make(cellseq(sources)); end
--- a/sequences/nil.m Mon Jan 21 11:01:45 2013 +0000 +++ b/sequences/nil.m Thu Jan 24 14:51:23 2013 +0000 @@ -1,5 +1,5 @@ % nil - empty sequence constructor % % nil :: void -> seq(_). -function s=nil, s=seq.NIL; end +function s=nil, s=seq.nil; end
--- a/sequences/slices.m Mon Jan 21 11:01:45 2013 +0000 +++ b/sequences/slices.m Thu Jan 24 14:51:23 2013 +0000 @@ -1,21 +1,19 @@ % slices - sequence obtained from slices of an array % % slices :: -% [[Size,M]->A] ~'array to slices', -% -> seq([[Size]->A]). +% [Size(1:E)->A] ~'E-dimensional array', +% -> seq([Size(1:E-1)->A]). % % slices :: -% [Size->A] ~'array to slices', -% D:natural ~'dimension of desired values' -% -> seq([Size:[[1,D]]->A]). +% [Size(1:E)->A] ~'E-dimensional array', +% D:natural ~'dimension of desired values' +% -> seq([arrset(Size,D,1)->A]). % % If 2nd parameter not given, the array is sliced along it's -% last non-singleton dimension, so the element size is the size -% after this dimension has been removed. If given, the dimension -% parameter cannot be smaller than the number of non-singleton -% dimensions in the input. +% last non-singleton dimension. In the second form, arrset(Size1,D,1) +% is the same as Size except that element D is set to 1. function y=slices(x,dim), - if nargin<2, dim=length(size(x))-1; end + if nargin<2, dim=length(size1(x)); end if isempty(x), y=nil; else y=seq.slices(x,dim); end end
--- a/sequences/subseqdata.m Mon Jan 21 11:01:45 2013 +0000 +++ b/sequences/subseqdata.m Thu Jan 24 14:51:23 2013 +0000 @@ -7,7 +7,7 @@ % -> data [[N,M]]. ~ 'resultant sequence'. o=map(@(r)extract(X,2,r),window(ranges)); if ~allequal(diff(ranges)) && ~isempty(o) - o=seq.resize([size(X,1),nan],o); + o=seq.resizer([size(X,1),nan],o); end end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sequences/window.m Thu Jan 24 14:51:23 2013 +0000 @@ -0,0 +1,19 @@ +% window - Window a sequnce of arrays in a given dimension +% +% window :: seq [[N,M]] -> seq [[N]]. +% window :: seq [[N,M]], L:natural -> seq [[N,L]]. +% window :: seq [[N,M]], L:natural, natural ~'hop size' -> seq [[N,L]]. +% +% This is just short for windowdata(...) +% Possible optimisation: +% when the span and hop are much less than the input buffer size +% and the source data does not have an efficient extract method, +% then it is worth caching the source data, ie window(cache(x),...) +function Y=window(X,varargin), + if nargin>1, Y=seq.windower.make(X,varargin{:}); + else + dim=length(size(X)); + if isseq(X), Y=concat(map(@(x)slices(x,dim),X)); + else Y=slices(X,dim); + end + end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sequences/window_ns.m Thu Jan 24 14:51:23 2013 +0000 @@ -0,0 +1,12 @@ +function Y=window_ns(X,W,H), +% window_ns - Window a sequnce of arrays in a given dimension (no strict size) +% +% window_ns :: seq [[N,M]] -> seq [[N]]. +% window_ns :: seq [[N,M]], L:natural -> seq [[N,L]]. +% window_ns :: seq [[N,M]], L:natural, natural ~'hop size' -> seq [[N,L]]. + +if nargin<2, W=1; H=1; +elseif nargin<3, H=W; +end + +Y=seq.windower.make(X,W,H,'strict',0);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/update_class Thu Jan 24 14:51:23 2013 +0000 @@ -0,0 +1,20 @@ +#!/bin/sh +cd "@$1" +cat > tmp <<EOF +classdef $1 < seq + properties (GetAccess=private, SetAccess=immutable) + end + methods +EOF +mkdir old +cat $1.m >> tmp +mv $1.m old +cat *.m >> tmp +mv *.m old +cat >> tmp <<EOF + end +end +EOF +mv old ../old/"@$1" +mv tmp $1.m +cd ..