function [wrap, unwrap] = arg_wrappers(varargin) %ARG_WRAPPERS return functions to turn multiple arrays into a vector and back % % [wrap, unwrap] = arg_wrappers(varargin) % % Give this function an example list of arrays/matrices. % It will return two functions: % "wrap" will take a list of arrays/matrices with the same sizes and return them % squished into a single column vector; "unwrap" will take the column vector and % return a cell array of arrays with the same sizes as the example list. % % Example usage: % >> [wrap, unwrap] = arg_wrappers(ones(2,3), ones(2,1)); % > X = wrap([1,4,5;2,7,8], [2;3])' % X = % 1 2 4 7 5 8 2 3 % >> [a, b] = celldeal(unwrap(X)) % a = % 1 4 5 % 2 7 8 % b = % 2 % 3 % % Intended use: providing generic routines, such as optimizers, with column % vectors, while making application-specific routines, such as cost functions, % not have to worry about the packing and unpacking of multiple parameters with % different sizes. % Iain Murray, November 2007 % I always return the same function for wrap, but I think it's nice to always % get the pair together, hence it being returned here rather than being a % separate function: wrap = @(varargin) cell2mat(cellmap(@(y) y(:)', varargin))'; % The unwrapping function depends on the sizes currently in use, so % constructing this function is somewhat more complicated: sizes = cellmap(@size, varargin); volumes = cellfun(@prod, sizes); ends = cumsum(volumes); starts = cumsum([1, volumes(1:end-1)]); ranges = num2cell([starts; ends], 1); % Black magic, sorry! %unwrap = @(x) celldeal(cellmap(@(z, n) reshape(z, sizes{n}), ... % cellmap(@(y) x(y(1):y(2)), ranges), num2cell(1:length(sizes)))); unwrap = @(x) cellmap(@(z, n) reshape(z, sizes{n}), ... cellmap(@(y) x(y(1):y(2)), ranges), num2cell(1:length(sizes)));