www.gusucode.com > mbc 工具箱 matlab 源码程序 > mbc/mbccellarrayeval.m
function varargout = mbccellarrayeval(hObjects, func, inArgs, outType) %MBCCCELLARRAYEVAL Evaluates a function for each cell in a cell array % % [OUT1, OUT2, ...] = MBCCCELLARRAYEVAL(CELL, FCN, INPUTARGS, OUTTYPE) % evaluates the function FCN over the cell array CELL. Additional input % arguments for FCN are specified by the cell array INPUTARGS which has % one cell for each input to FCN. The output types for the function % returns can be specified by function handles in OUTTYPE. The outputs % are a set of arrays the same size as CELL, one array for each output % requested from FCN. % % Input Specification % =================== % Each cell of INPUTARGS must contain either a cell array the same size as % the input cell array, a single cell or not be a cell. Input arguments % that are not cells or are single cells are "scalar expanded": they (or % their contents) are passed in to each function evaluation. Input % arguments that are a cell array are referenced and the corresponding % cell's contents are passed to each function evaluation. % % If you need to pass a cell array as an argument to each evaluation, you % should wrap this in another cell so that the method knows that that cell % contents should be scalar expanded. % % Output Specification % ==================== % The output arrays can be either specified as a particular type, or left % to be a cell array containment of the outputs. Outputs types are % defined by specifying a cell array of function handles, one for each % output. Each function handle is called in turn with a dimension vector % as input in order to initialise an output array. If a cell contains an % empty matrix, this specifies that the outputs should be captured and put % into separate cells of a cell array. % % For convenience, there is a set of methods that generate function % handles for all of the common types. These methods are: mbcdouble, % mbclogical, mbcpointer, mbcuint8, mbcuint32. % % Example: % % >> p = repmat({cgvariable}, 2,4); % >> mbccellarrayeval(p, @getvalue, {}, mbcdouble) % % ans = % % 0 0 0 0 % 0 0 0 0 % Copyright 2000-2008 The MathWorks, Inc. and Ford Global Technologies, Inc. persistent loopers; if ~iscell(hObjects) error(message('mbc:mbccellarrayeval:InvalidArgument')); end ptrDim = size(hObjects); numOut = max(1, nargout); % Check output specifiers outputIsCellRef = true(1, numOut); varargout = cell(1, numOut); if nargin<4 || isempty(outType) % Do not need to initialise outputs: the looper chosen for this case % will do it more efficiently elseif isa(outType, 'function_handle') outputIsCellRef(1) = false; varargout{1} = outType(ptrDim); else if length(outType)>numOut outType = outType(1:numOut); end hasType = ~cellfun('isempty', outType); if ~any(hasType) % Do not need to initialise outputs: the looper chosen for this case % will do it more efficiently else outputIsCellRef(1:length(outType)) = ~hasType; idx = find(hasType); for n = idx varargout{n} = outType{n}(ptrDim); end if any(outputIsCellRef) c = {cell(ptrDim)}; varargout(outputIsCellRef) = c; end end end % Make sure evaluation function is a function handle if ischar(func) func = str2func(func); end % Do any required scalar expansion of inputs if nargin<3 inputIsCell = {}; else numIn = length(inArgs); if numIn isCellArray = cellfun('isclass', inArgs, 'cell'); if ~any(isCellArray) inputIsCell = inArgs; elseif length(inArgs)==1 inputIsCell = inArgs{1}(:); else cellLength = cellfun('prodofsize', inArgs)>1; if all(isCellArray) && all(cellLength==1) inputIsCell = [inArgs{:}]; elseif any(isCellArray) % make matrix of input arguments inputIsCell= cell(numel(hObjects), numIn); for n = 1:numIn if isCellArray(n) inputIsCell(:,n) = inArgs{n}(:); elseif isa(inArgs{n}, 'cell') % scalar expansion of cell input inputIsCell(:,n) = inArgs{n}; else % Scalar expansion of non-cell input inputIsCell(:,n) = inArgs(n); end end end end else inputIsCell = inArgs; end end % Decide which evaluation looper to use if isempty(loopers) loopers = {@i_loop_1_array, @i_loop_2_array, @i_loop_1_cell, @i_loop_all_cell, @i_loop_general}; end if numOut==1 && ~outputIsCellRef evalLoop = loopers{1}; elseif numOut==2 && ~any(outputIsCellRef) evalLoop = loopers{2}; elseif numOut==1 && outputIsCellRef evalLoop = loopers{3}; elseif all(outputIsCellRef) evalLoop = loopers{4}; else evalLoop = loopers{5}; end % Execute looping evaluation varargout = evalLoop(varargout, outputIsCellRef, hObjects, func, inputIsCell); % ------------------------------------------------------------------------- % Looping function for case where outputs are all cell referenced arrays % ------------------------------------------------------------------------- function output = i_loop_all_cell(output, outputIsCellRef, hObjects, func, inputIsCell) funcoutput = cell(numel(hObjects),length(output)); if isempty(inputIsCell) for n = 1:numel(hObjects) [funcoutput{n, :}] = func(hObjects{n}); end elseif size(inputIsCell, 1)==1 for n = 1:numel(hObjects) [funcoutput{n, :}] = func(hObjects{n}, inputIsCell{:}); end else for n = 1:numel(hObjects) [funcoutput{n, :}] = func(hObjects{n}, inputIsCell{n,:}); end end ptrDim = size(hObjects); for n = 1:length(output) output{n} = reshape(funcoutput(:,n), ptrDim); end % ------------------------------------------------------------------------- % Looping function for case where output is a two outputs that are typed % arrays % ------------------------------------------------------------------------- function output = i_loop_2_array(output, outputIsCellRef, hObjects, func, inputIsCell) if isempty(inputIsCell) for n = 1:numel(hObjects) [output{1}(n), output{2}(n)] = func(hObjects{n}); end elseif size(inputIsCell, 1)==1 for n = 1:numel(hObjects) [output{1}(n), output{2}(n)] = func(hObjects{n}, inputIsCell{:}); end else for n = 1:numel(hObjects) [output{1}(n), output{2}(n)] = func(hObjects{n}, inputIsCell{n,:}); end end % ------------------------------------------------------------------------- % Looping function for case where output is a single output that is a typed % array % ------------------------------------------------------------------------- function output = i_loop_1_array(output, outputIsCellRef, hObjects, func, inputIsCell) nOut = numel(hObjects); if isempty(inputIsCell) for n = 1:nOut output{1}(n) = func(hObjects{n}); end elseif size(inputIsCell, 1)==1 for n = 1:nOut output{1}(n) = func(hObjects{n}, inputIsCell{:}); end else for n = 1:nOut output{1}(n) = func(hObjects{n}, inputIsCell{n,:}); end end % ------------------------------------------------------------------------- % Looping function for case where output is a single output that is a cell % referenced cell array % ------------------------------------------------------------------------- function output = i_loop_1_cell(output, outputIsCellRef, hObjects, func, inputIsCell) % When outputs are all cells, they are not initialized before coming in % here. In this function we need to initialise it before using it output{1} = cell(size(hObjects)); if isempty(inputIsCell) for n = 1:numel(hObjects) output{1}{n} = func(hObjects{n}); end elseif size(inputIsCell, 1)==1 for n = 1:numel(hObjects) output{1}{n} = func(hObjects{n}, inputIsCell{:}); end else for n = 1:numel(hObjects) output{1}{n} = func(hObjects{n}, inputIsCell{n,:}); end end % ------------------------------------------------------------------------- % General looper. % ------------------------------------------------------------------------- function output = i_loop_general(output, outputIsCellRef, hObjects, func, inputIsCell) cellidx = find(outputIsCellRef); notcellidx = find(~outputIsCellRef); outcell = cell(1, length(output)); if isempty(inputIsCell) for n = 1:numel(hObjects) [outcell{:}] = func(hObjects{n}); for m = cellidx output{m}{n} = outcell{m}; end for m = notcellidx output{m}(n) = outcell{m}; end end elseif size(inputIsCell, 1)==1 for n = 1:numel(hObjects) [outcell{:}] = func(hObjects{n}, inputIsCell{:}); for m = cellidx output{m}{n} = outcell{m}; end for m = notcellidx output{m}(n) = outcell{m}; end end else for n = 1:numel(hObjects) [outcell{:}] = func(hObjects{n}, inputIsCell{n,:}); for m = cellidx output{m}{n} = outcell{m}; end for m = notcellidx output{m}(n) = outcell{m}; end end end