samer@4: function [f,Y]=history_nest(fields,dim,H) samer@4: % history_nest - return state transformer that logs old states samer@4: % samer@4: % history :: samer@4: % F:{[N]->string} ~'list of field names', samer@4: % natural ~'dimension to cat along (defaults to 1)', samer@4: % struct F ~'old history to build on' samer@4: % -> (history(A,F) ->history(A,F)), samer@4: % history(A,F). samer@4: % samer@4: % history(A,F) ~ 'structure A with history of fields F' ::= samer@4: % struct { samer@4: % current :: struct A ~'original fields from A'; samer@4: % history :: struct F ~ 'sub-struct containing fields F' samer@4: % }. samer@4: % samer@4: % This function returns a state transformer function. The state MUST be samer@4: % a structure but it can have any fields. The history mechanism adds the samer@4: % field 'history' which contains the histories of certain fields from samer@4: % the main structure. The returned function concatenates the current samer@4: % values of the named fields onto the end of the corresponding fields samer@4: % in the history, if X is a sequence whose elements contain a field samer@4: % called 'cost', then samer@4: % samer@4: % [logcost,H0]=history({'cost'},1); samer@4: % Y=scandata(logcost,H0,X); samer@4: % samer@4: % Elements of Y will have fields 'current' and 'history' which samer@4: % contain values from X and a history of 'cost' respectively. samer@4: samer@4: g=@logfields_scanner; samer@4: if nargin<2, dim=1; end samer@4: if nargin<3, H=struct; end samer@4: samer@4: for i=1:length(fields) samer@4: % initialise history fields if not present already samer@4: if ~isfield(H,fields{i}), samer@4: H.(fields{i}) = []; samer@4: end samer@4: end samer@4: samer@4: f=@logfields; samer@4: Y.current=[]; samer@4: Y.history=H; samer@4: samer@4: function Y=logfields(Y,X) samer@4: Y.current=X; samer@4: Y.history=logfields_scanner(Y.history,X); samer@4: end samer@4: samer@4: function H=logfields_scanner(H,X) samer@4: for i=1:length(fields) samer@4: field=fields{i}; samer@4: H.(field) = cat(dim,H.(field),X.(field)); samer@4: end samer@4: end samer@4: end samer@4: samer@4: samer@4: samer@4: