changeset 13:03694e5c8365

Reorganised some high order list functions to correct class-based method dispatch; fixed some docs.
author samer
date Wed, 16 Jan 2013 12:12:34 +0000
parents fbc0540a9208
children 1ec17635de0e
files general/algo/iterate.m general/algo/optpause.m general/arrutils/.DS_Store general/arrutils/chunk.m general/arrutils/defmat.m general/arrutils/flatten.m general/arrutils/foldrcols.m general/arrutils/forels.m general/arrutils/interleave.m general/arrutils/reverse.m general/arrutils/shiftl.m general/arrutils/shiftr.m general/arrutils/tween.m general/cellutils/cellmap.m general/cellutils/cfoldl.m general/cellutils/cfoldr.m general/cellutils/cforeach.m general/cellutils/cmapaccum.m general/cellutils/cscanl.m general/cpfields.m general/funutils/@function_handle/decorate.m general/funutils/@function_handle/foldl.m general/funutils/@function_handle/foldr.m general/funutils/@function_handle/foreach.m general/funutils/@function_handle/map.m general/funutils/@function_handle/scanl.m general/funutils/@function_handle/select.m general/funutils/@function_handle/zipwith.m general/funutils/TODO general/funutils/foreach.m general/pair.m sched/pair.m sequences/@seq/foldl.m sequences/@seq/seq.m
diffstat 34 files changed, 222 insertions(+), 73 deletions(-) [+]
line wrap: on
line diff
--- a/general/algo/iterate.m	Mon Jan 14 22:21:11 2013 +0000
+++ b/general/algo/iterate.m	Wed Jan 16 12:12:34 2013 +0000
@@ -12,23 +12,21 @@
 %       (A->(A | empty)) ~'function to iterate, can return [] to terminate',
 %       A                ~'initial state'
 %    }                   ~'iterated system as a cell array',
-%    options iterate_timed_options
+%    options iterate_options
 % -> A                ~'final state'.
 %
-% iterate_timed_options = {
+% iterate_options = {
 %       its     :: natural /inf ~'Iteration limit';
-%       quiet   :: bool    /1   ~'controls console display';
-%       drawnow :: bool  /1   ~'controls graphics updating';
+%       quiet   :: bool    /1   ~'controls verbosity';
 %       pre     :: A=>void      ~'something to do before each iteration';
 %       post    :: A=>void      ~'something to do after each iteration';
 %       save    :: natural /0   ~'iterations between state saving (0=off)';
 %       id      :: string  /'iterstate@' ~'name of mat file to save to';
-%       recover :: bool  /0   ~'recover from saved state'
+%       recover :: bool    /0   ~'recover from saved state';
+%       drawnow :: bool    /1   ~'controls graphics updating';
+%       pause   :: natural /0   ~'pause between iterations (in ms) or 1 for indefinite'
 %    }.
 %
-%	Plus the usual OPTPAUSE options.
-%
-% NOTE: old termination by throwing an exception is no longer supported.
 % The function must return an empty array to force termination.
 
 if iscell(varargin{1})
@@ -67,7 +65,6 @@
 		fprintf('Will save every %d iterations to %s.mat\n',opts.save,opts.id);
 	end
 
-	% how cunning is this...
 	if isfinite(opts.its), itformat=sprintf('%%%dd. ',ceil(log10(opts.its)));
 	else itformat='%d. '; end
 
--- a/general/algo/optpause.m	Mon Jan 14 22:21:11 2013 +0000
+++ b/general/algo/optpause.m	Wed Jan 16 12:12:34 2013 +0000
@@ -2,8 +2,8 @@
 % optpause - Optionally pause and/or update graphics
 %
 % optpause :: struct {
-%    pause :: natural/0 ~'0-nopause, 1-pause, N-timed pause in ms';
-%    drawnow :: bool/0  ~'flush graphics before pausing'
+%    pause   :: nonneg/0 ~'0-nopause, 1-pause, N-timed pause in ms';
+%    drawnow :: bool/0  ~'flush graphics if not pausing'
 % } => void.
 
 ps=getparam(opt,'pause',0);
Binary file general/arrutils/.DS_Store has changed
--- a/general/arrutils/chunk.m	Mon Jan 14 22:21:11 2013 +0000
+++ b/general/arrutils/chunk.m	Wed Jan 16 12:12:34 2013 +0000
@@ -1,9 +1,11 @@
 function B=chunk(A,n,step)
-% CHUNK: return chunk from inside matrix
-% B=chunk(A,n,hop): returns nth block of rows of size hop from A
-% A:  source matrix
-% n:  index of chunk
-% hop: size of chunk
+% chunk - return chunk from inside matrix
+%
+% chunk :: 
+%    [[N,M]]   ~'source array',
+%    K:natural ~'index of chunk',
+%    L:natural ~'chunk size'
+% -> [[L,M]]   ~'K block of L rows'.
 
 i=n*step+1;
 B=A(i:i+step-1,:);
--- a/general/arrutils/defmat.m	Mon Jan 14 22:21:11 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-function X=defmat(I,w,D)
-% defmat - specify matrix as a list of non-zero elements
-%
-% defmat ::
-%    [[N,E]->natural]   ~'N E-dim array subscripts, 1 per row',
-%    [[N]]              ~'values to place at positions specified by subs',
-%    D:[[1,E]]          ~'size of target array'
-% -> [[D]]              ~'array of size D'.
-
-X=accumarray(I,w);
-if any(size(X)<D)
-	J=num2cell(D);
-	X(J{:})=0;
-end
--- a/general/arrutils/flatten.m	Mon Jan 14 22:21:11 2013 +0000
+++ b/general/arrutils/flatten.m	Wed Jan 16 12:12:34 2013 +0000
@@ -1,6 +1,4 @@
-function X=flatten(X);
 % flatten - convert array into column vector
 %
 % flatten :: [[size]]->[[prod(size)]]
-
-X=reshape(X,numel(X),1);
+function X=flatten(X), X=X(:); end
--- a/general/arrutils/foldrcols.m	Mon Jan 14 22:21:11 2013 +0000
+++ b/general/arrutils/foldrcols.m	Wed Jan 16 12:12:34 2013 +0000
@@ -1,4 +1,6 @@
-% foldcols :; 
+% foldrcols - fold array columns from the right
+%
+% foldrcols :; 
 %    ([[M]], [[N]] -> [[M]])   ~'folding function',
 %    [[M]]                     ~'initial value',
 %    [[N,L]]                   ~'data to scan, sequence of length L'
--- a/general/arrutils/forels.m	Mon Jan 14 22:21:11 2013 +0000
+++ b/general/arrutils/forels.m	Wed Jan 16 12:12:34 2013 +0000
@@ -1,19 +1,16 @@
-function forels(f,X,varargin)
 % forels - do an action for each element of an array in order
 %
 % forels :: 
 %    (A->action) ~'action to apply to each element', 
 %    [[Size]->A] ~'array of elements of type',
-%    options {
-%       pause :: bool/0
-%       drawnow :: bool/1
-%    }           ~'see ITERATE for more options'
-% -> action.
+%    options iterate_options
+% => void.
 %
 % Note, the array can be multidimensional - the standard order
 % cycles through the earlier indices before the later ones, eg
 % rows, then columns, then slices etc.
 
+function forels(f,X,varargin)
 	N=numel(X);
 	iterate(@g,1,varargin{:});
 
--- a/general/arrutils/interleave.m	Mon Jan 14 22:21:11 2013 +0000
+++ b/general/arrutils/interleave.m	Wed Jan 16 12:12:34 2013 +0000
@@ -1,5 +1,11 @@
+% interleave - interleave elements of an array
+%
+% interleave :: [[1,N]], [[1,M]] -> [[1,N+M]].
+%
+% interleave(A,B) interleaves the elements of A and B until there are
+% no elements left in one of them. The remaining elements of the other
+% are then appending. 
 function z=interleave(x,y)
-% interleave - interleave elements of an array
 
 x=x(:);
 y=y(:);
--- a/general/arrutils/reverse.m	Mon Jan 14 22:21:11 2013 +0000
+++ b/general/arrutils/reverse.m	Wed Jan 16 12:12:34 2013 +0000
@@ -1,3 +1,7 @@
-function y=reverse(x)
-% reverse a vector
-y = x(length(x):-1:1);
+% reverse - reverse a vector
+%
+% reverse :: [[N]] -> [[N]].
+% reverse :: [[1,N]] -> [[1,N]].
+%
+% Works on row or column vectors, preserving orientation.
+function y=reverse(x), y = x(length(x):-1:1); end
--- a/general/arrutils/shiftl.m	Mon Jan 14 22:21:11 2013 +0000
+++ b/general/arrutils/shiftl.m	Wed Jan 16 12:12:34 2013 +0000
@@ -1,9 +1,13 @@
+% shiftl - shift a column vector up one
+%
+% shift :: [[N,M]] -> [[N,M]].
+%
+% Shift array elements back one, padding end with zeros.
+% eg [ 1 2 3 4 ] --> [ 2 3 4 0]
 function y=shiftl(x)
-% shiftl - shift a column vector up one
-% maintaining original length
-% eg [ 1 2 3 4 ] --> [ 2 3 4 0]
-if isvector(x)
-	y = [ x(2:length(x)); 0];
-else
-	y = [ x(:,2:size(x,2)), zeros(size(x,1),1) ];
+	if isvector(x)
+		y = [ x(2:end); 0];
+	else
+		y = [ x(:,2:size(x,2)), zeros(size(x,1),1) ];
+	end
 end
--- a/general/arrutils/shiftr.m	Mon Jan 14 22:21:11 2013 +0000
+++ b/general/arrutils/shiftr.m	Wed Jan 16 12:12:34 2013 +0000
@@ -1,5 +1,13 @@
+% shiftr - shift array columns right one
+%
+% shiftr :: [[N,M]] -> [[N,M]].
+%
+% Shift array elements right one, padding start with zeros.
+% eg [ 1 2 3 4 ] --> [ 0 1 2 3 ]
 function y=shiftr(x)
-% shiftr - shift a column vector down one
-% maintaining original length
-% eg [ 1 2 3 4 ] --> [ 0 1 2 3 ]
-y = [0; x(1:length(x)-1) ];
+	if isvector(x)
+		y = [ 0; x(1:end-1) ];
+	else
+		y = [ zeros(size(x,1),1), x(:,1:size(x,2)-1) ];
+	end
+end
--- a/general/arrutils/tween.m	Mon Jan 14 22:21:11 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-function I=tween(a,b)
-% tween - all indices in a given range (like interval to set)
-%
-% tween :: interger, integer -> [[N]->integer].
-% tween :: [[2]->interger] -> [[N]->integer].
-%
-% tween([A,B])=tween(A,B).
-
-if nargin<2, b=a(2); a=a(1); end
-if b>=a, I=a:b; else I=a:-1:b; end
-
--- a/general/cellutils/cellmap.m	Mon Jan 14 22:21:11 2013 +0000
+++ b/general/cellutils/cellmap.m	Wed Jan 16 12:12:34 2013 +0000
@@ -1,7 +1,7 @@
 function Y=cellmap(fn,X)
 % cellmap - Map a function over a cell array
 %
-% cellmap :: (A->B, {[Size]->A}) -> {[Size]->B}
+% cellmap :: (A->B, {[Size]->A}) -> {[Size]->B}.
 
 % preallocate to fix size
 Y=cell(size(X));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/general/cellutils/cfoldl.m	Wed Jan 16 12:12:34 2013 +0000
@@ -0,0 +1,9 @@
+function X=cfoldl(fn,e,args)
+% cfoldl - Fold fom the left combinator for cell arrays
+%
+% foldl :: (X,Y->X), X, cells(Y) -> X.
+%
+% This function applies a folding function to cell array,
+% starting from the left using the given starting element.
+% eg cfoldl(@plus,0,{1,2,3,4}) = ((((0+1)+2)+3)+4).
+X=e; for i=1:length(args), X=fn(X,args{i}); end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/general/cellutils/cfoldr.m	Wed Jan 16 12:12:34 2013 +0000
@@ -0,0 +1,13 @@
+function X=foldr(fn,e,args)
+% foldr - Fold from the right for cell arrays
+%
+% This function applies an operator to a list of arguments,
+% starting from the right, eg
+% elements, eg foldr(@plus,0,{1,2,3,4}) = (1+(2+(3+(4+0)))).
+%
+% foldr :: 
+%    (Y,X->X)	~'associative binary operator',
+%    Y         ~'initial element',
+%    {[N]->Y} ~'list (cell array) of arguments'
+% -> Y.
+X=e; for i=length(args):-1:1, X=fn(args{i},X); end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/general/cellutils/cforeach.m	Wed Jan 16 12:12:34 2013 +0000
@@ -0,0 +1,8 @@
+function foreach(f,X,varargin)
+% foreach - do an action for each element in a cell array in order
+%
+% foreach :: (A=>void), {[N]->A} => void.
+%
+
+if nargin>2, error('Options for foreach no longer supported'); end
+for i=1:numel(X), f(x{i}); end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/general/cellutils/cmapaccum.m	Wed Jan 16 12:12:34 2013 +0000
@@ -0,0 +1,10 @@
+function [Y,s]=cmapaccum(fn,s,X)
+% cmapaccum - Map a function over a cell array
+%
+% cmapaccum :: (A,S->B,S), S, {[Size]->A}) -> {[Size]->B}, S.
+
+% preallocate to fix size
+Y=cell(size(X));
+for i=1:numel(X)
+	[Y{i},s]=fn(X{i},s);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/general/cellutils/cscanl.m	Wed Jan 16 12:12:34 2013 +0000
@@ -0,0 +1,24 @@
+% cscanl - scanl for cell arrays
+%
+% cscanl :: 
+%    (S,X->S)   ~'scannning function',
+%    S          ~'initial value',
+%    {[N]->X}   ~'data to scan, sequence of length L'
+% -> {[N]->S}.
+
+function Y=cscanl(f,y,X,varargin)
+	Y=cell(size(X));
+	if nargin>3
+		opts=prefs('draw',0,varargin{:});
+		for i=1:size(X,2)
+			y1=f(y,X{i});
+			Y{i}=y1;
+			if opts.draw, opts.plotfn(i,y,X{i},y1);  end
+			optpause(opts);
+			y=y1;
+		end
+	else
+		for i=1:size(X,2), y=f(y,X{i}); Y{i}=y; end
+	end
+		
+
--- a/general/cpfields.m	Mon Jan 14 22:21:11 2013 +0000
+++ b/general/cpfields.m	Wed Jan 16 12:12:34 2013 +0000
@@ -7,5 +7,6 @@
 % -> struct union(B,C) ~'struct with fields B union C' :-
 %  	subset(C,A)      ~'target fields must be in A'.
 function B=cpfields(fields,A,B)
+keyboard
 	B=foldl(@(b,fn)setfield(b,fn,getfield(A,fn)),B,fields);
 		
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/general/funutils/@function_handle/decorate.m	Wed Jan 16 12:12:34 2013 +0000
@@ -0,0 +1,23 @@
+% decorate - Decorate function with pre and post operations and optional pausing
+%
+% decorate :: 
+%    (A->B{:})   ~'function from 1 argument to any number of returns', 
+%    options {
+%       pre  :: (A=>void)/@nop   ~'action to perform before calling function';
+%       post :: (A=>void)/@nop   ~'action to perform after calling function'
+%    } 
+% -> (A->B{:}) ~'new function incorporating pre and post actions'.
+function f1=decorate(f,varargin)
+	opts=prefs(varargin{:});
+	pf=pauser(opts);
+	if isfield(opts,'pre') || isfield(opts,'post')
+		pre=getparam(opts,'pre',@nop);
+		post=getparam(opts,'post',@nop);
+		f1=@f_bracket;
+	else
+		f1=@f_simple;
+	end
+
+	function x=f_simple(x), x=f(x); pf(); end
+	function x=f_bracket(x), pre(x); x=f(x); post(x); pf(); end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/general/funutils/@function_handle/foldl.m	Wed Jan 16 12:12:34 2013 +0000
@@ -0,0 +1,5 @@
+function X=foldl(fn,e,args)
+% foldl - Fold fom the left combinator 
+%
+% foldl :: (X,Y->X), X, cells(Y) -> X.
+X=e; for i=1:length(args), X=fn(X,args{i}); end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/general/funutils/@function_handle/foldr.m	Wed Jan 16 12:12:34 2013 +0000
@@ -0,0 +1,9 @@
+function X=foldr(fn,e,args)
+% foldr - Fold from the right combinator 
+%
+% foldr :: (Y,X->X),	Y, cells(Y) -> Y.
+%
+% This function applies an associative operator to a list of arguments,
+% starting from the right, eg
+% elements, eg foldr(@plus,0,{1,2,3,4}) = (1+(2+(3+(4+0)))).
+X=e; for i=length(args):-1:1, X=fn(args{i},X); end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/general/funutils/@function_handle/foreach.m	Wed Jan 16 12:12:34 2013 +0000
@@ -0,0 +1,7 @@
+function foreach(f,X,varargin)
+% foreach - do an action for each element in a cell array in order
+%
+% foreach :: (A=>void), cells(A) => void.
+
+if nargin>2, error('Options for foreach no longer supported'); end
+for i=1:numel(X), f(x{i}); end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/general/funutils/@function_handle/map.m	Wed Jan 16 12:12:34 2013 +0000
@@ -0,0 +1,4 @@
+% map - Map a function over a cell array
+%
+% map :: (A->B, {[Size]->A}) -> {[Size]->B}
+function Y=map(fn,X), Y=cellmap(fn,X); end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/general/funutils/@function_handle/scanl.m	Wed Jan 16 12:12:34 2013 +0000
@@ -0,0 +1,8 @@
+% scanl - scanl for cell arrays
+%
+% scanl :: 
+%    (S,X->S)   ~'scannning function',
+%    S          ~'initial value',
+%    {[N]->X}   ~'data to scan, sequence of length L'
+% -> {[N]->S}.
+function Y=scanl(f,y,X), Y=cscanl(f,y,X); end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/general/funutils/@function_handle/select.m	Wed Jan 16 12:12:34 2013 +0000
@@ -0,0 +1,7 @@
+% select - Filter cell array with boolean test
+%
+% select :: (A->bool), {[N]->A} -> {[M]->A}.
+% select :: (A->bool), {[1,N]->A} -> {[1,M]->A}.
+%
+% eg, select(@iseven,{1,2,3,4}) = {2,4}
+function Y=select(fn,X), Y=cellfilt(fn,X); 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/general/funutils/@function_handle/zipwith.m	Wed Jan 16 12:12:34 2013 +0000
@@ -0,0 +1,11 @@
+function Y=zipwith(fn,varargin)
+% zipwith - Zip cell arrays with a function 
+%
+% zipwith :: (
+% 	(D1,...,Dn)->R	                  ~ function of n arguments,
+% 	 {[size]->D1}, ..., {[size]->Dn}	~ n cell arrays of appropriate types
+% ) -> {[size]->R}                	~ cell array of results
+
+Y=cellzip(fn,varargin{:});
+
+	
--- a/general/funutils/TODO	Mon Jan 14 22:21:11 2013 +0000
+++ b/general/funutils/TODO	Wed Jan 16 12:12:34 2013 +0000
@@ -13,4 +13,8 @@
 	folder:             X,S->S
 	accum:              Y,S->X,S
 
+Current special cases:
+	scanner_add_plotter
+	decorate
+
 Also what about actions? (Function with side-effects or dependence on global state)
--- a/general/funutils/foreach.m	Mon Jan 14 22:21:11 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-function foreach(f,x), if ~isempty(x), error('foreach not supported for this class'); end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/general/pair.m	Wed Jan 16 12:12:34 2013 +0000
@@ -0,0 +1,1 @@
+function p=pair(a,b), p={a,b};
--- a/sched/pair.m	Mon Jan 14 22:21:11 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-function p=pair(a,b), p={a,b};
--- a/sequences/@seq/foldl.m	Mon Jan 14 22:21:11 2013 +0000
+++ b/sequences/@seq/foldl.m	Wed Jan 16 12:12:34 2013 +0000
@@ -10,6 +10,7 @@
 %    seq(Y)    ~'a lazy sequence'
 % -> X.
 
+if iscell(y), x=cfoldl(fn,e,y); return; end
 if nargin<4,
 	x=e; 
 	while ~isempty(y)
--- a/sequences/@seq/seq.m	Mon Jan 14 22:21:11 2013 +0000
+++ b/sequences/@seq/seq.m	Wed Jan 16 12:12:34 2013 +0000
@@ -91,12 +91,16 @@
 		% once :: seq A -> seq A.
 		function Y=once(X), Y=cons(head(X),[]); end
 
-		function x=map(fn,e,varargin), x=seq.map(fn,e,varargin{:}); end
-		function x=mapaccum(fn,s0,y), x=seq.mapaccum(fn,s0,y); end
+		function x=map(fn,y), x=seq.map(fn,y); end
 		function x=select(fn,y), x=seq.select(fn,y); end
 		function y=cache(x), y=seq.cache(x); end
 		function y=buffer(x,varargin), y=seq.buffer(x,varargin{:}); end
 
+		function x=mapaccum(fn,s0,y)
+			if iscell(y), x=cmapaccum(fn,s0,y);
+			else x=seq.mapaccum(fn,s0,y); end
+		end
+
 		% scanl - scanl combinator for sequences
 		%
 		% This function applies an associative operator to a list of arguments,
@@ -107,7 +111,10 @@
 		%    X         ~'initial element',
 		%    seq Y     ~'a sequence'
 		% -> seq X.
-		function x=scanl(fn,e,y,varargin), x=seq.scanl(fn,e,y,varargin{:}); end
+		function x=scanl(fn,e,y,varargin), 
+			if iscell(y), x=cscanl(fn,e,y,varargin{:});
+			else x=seq.scanl(fn,e,y,varargin{:}); end
+		end
 
 		% concat - Concatenate sequences
 		%
@@ -160,7 +167,13 @@
 		%    S,
 		%    seq(A), seq(B), ...
 		% -> seq(X).
-		function x=zipaccum(fn,s0,varargin), x=seq.zipaccum(fn,s0,varargin); end
+		function x=zipaccum(fn,s0,varargin), 
+			if isseq(s0) && any(map(@iscell,varargin)) % catch dispatching errors
+				z=czipcaccum(fn,s0,varargin{:});
+			else
+				x=seq.zipaccum(fn,s0,varargin); 
+			end
+		end
 
 		function xx=unzip(y)
 			% unzip - Separate sequence of tuples into several sequences