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.
author samer
date Thu, 24 Jan 2013 14:51:23 +0000
parents f1ce7876346a
children beb8a3f4a345
files audio/playaudio_async.m audio/playaudio_unfold.m dsp/README.txt dsp/synth/addsynth.m dsp/synth/audio_sonifier.m dsp/synth/blockdata.m dsp/synth/shepardtone.m dsp/synth/sonify.m dsp/synth/sonify_disc.m dsp/synth/srdata.m dsp/synth/unbuffer_nu.m general/arrutils/.DS_Store general/fileutils/loadmat.m sequences/+seq/.window.m (gort's conflicted copy 2013-01-24).swp sequences/+seq/bindcat.m sequences/+seq/binder.m sequences/+seq/buffer.m sequences/+seq/bufferer.m sequences/+seq/cache.m sequences/+seq/cacher.m sequences/+seq/concat.m sequences/+seq/concatenator.m sequences/+seq/condtaker.m sequences/+seq/cycle.m sequences/+seq/cycler.m sequences/+seq/map.m sequences/+seq/mapaccum.m sequences/+seq/mapper.m sequences/+seq/merge.m sequences/+seq/merger.m sequences/+seq/resize.m sequences/+seq/resizer.m sequences/+seq/scanl.m sequences/+seq/scanner.m sequences/+seq/select.m sequences/+seq/selector.m sequences/+seq/skin.m sequences/+seq/skinner.m sequences/+seq/slices.m sequences/+seq/stmapper.m sequences/+seq/stzipper.m sequences/+seq/subsample.m sequences/+seq/subsampler.m sequences/+seq/take.m sequences/+seq/taker.m sequences/+seq/takewhile.m sequences/+seq/window.m sequences/+seq/windower.m sequences/+seq/zipaccum.m sequences/+seq/zipper.m sequences/+seq/zipwith.m sequences/@seq/seq.m sequences/@seq/skin.m sequences/@seq/window.m sequences/@seq/window_ns.m sequences/concatseqs.m sequences/nil.m sequences/slices.m sequences/subseqdata.m sequences/window.m sequences/window_ns.m update_class
diffstat 62 files changed, 993 insertions(+), 878 deletions(-) [+]
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);
Binary file general/arrutils/.DS_Store has changed
--- 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)
Binary file sequences/+seq/.window.m (gort's conflicted copy 2013-01-24).swp has changed
--- 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 ..