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