gusucode.com > bigdata 工具箱 matlab源码程序 > bigdata/@tall/private/minmaxop.m
function [out, varargout] = minmaxop(fcn, arg1, arg2, varargin) %#ok<STOUT> %MINMAXOP Common helper for MIN and MAX. % Copyright 2015-2016 The MathWorks, Inc. narginchk(2, 5); FCN_NAME = upper(func2str(fcn)); if nargout > 1 % Currently don't support the index output for min/max. error(message('MATLAB:bigdata:array:MinMaxSingleOutput')); end checkNotTall(FCN_NAME, 2, varargin{:}); ALLOWED_TYPES = {'numeric', 'logical', 'categorical', 'duration', 'datetime', 'char'}; % We can check 'arg1' right now - we can't check arg2 until we've worked out % whether it is intended to be data or not. arg1 = tall.validateType(arg1, FCN_NAME, ALLOWED_TYPES, 1); % If we have a second argument, it might be: a tall data argument; a small data % argument; [] to indicate we're in reduction mode (provided a dimension is % specified); or (erroneously) a flag. if nargin > 2 isValidDimFcn = @(x) isscalar(x) && (isnumeric(x) || islogical(x)); if nargin == 5 || (nargin == 4 && ~ischar(varargin{1})) dim = varargin{1}; flags = varargin(2:end); operation = 'ReduceInDim'; if ~iIsSmallEmpty(arg2) % Must be [] error(message(sprintf('MATLAB:%s:caseNotSupported', lower(FCN_NAME)))); end if ~isValidDimFcn(dim) error(message('MATLAB:getdimarg:dimensionMustBePositiveInteger')); end elseif iIsSmallEmpty(arg2) % If we have a dimension, then we're reducing in that dimension, otherwise this % is treated as a comparison if nargin > 3 && isValidDimFcn(varargin{1}) dim = varargin{1}; operation = 'ReduceInDim'; flags = varargin(2:end); elseif nargin > 3 operation = 'ReduceInDefaultDim'; flags = varargin; else operation = 'Comparison'; flags = varargin; end else % Treat as comparison operation = 'Comparison'; flags = varargin; end else % Must be reduction in default dimension. No flags permitted. operation = 'ReduceInDefaultDim'; flags = {}; end % Derive the output adaptor - need this to interpret reduction flags switch operation case 'Comparison' % Take the opportunity to validate arg2 now that we know it is data. arg2 = tall.validateType(arg2, FCN_NAME, ALLOWED_TYPES, 2); outAdaptor = iDeriveComparisonAdaptor(arg1, arg2); case 'ReduceInDim' outAdaptor = iDeriveReduceInDimAdaptor(arg1, dim); case 'ReduceInDefaultDim' outAdaptor = iDeriveReduceInDefaultDimAdaptor(arg1); end [nanFlagCell, precisionFlagCell] = interpretReductionFlags(outAdaptor, FCN_NAME, flags); % Note that by this point we know that in the reduction cases the first % input is tall since the second must be a non-tall empty. switch operation case 'Comparison' % Perform the elementwise comparison [arg1, arg2] = iCheckAtLeastOneTallAndBroadcast(FCN_NAME, arg1, arg2); out = elementfun(@(x,y) fcn(x, y, nanFlagCell{:}, precisionFlagCell{:}), arg1, arg2); out.Adaptor = outAdaptor; case 'ReduceInDim' if dim == 1 out = reducefun(@(x) fcn(x, [], dim, nanFlagCell{:}, precisionFlagCell{:}), arg1); else out = slicefun(@(x) fcn(x, [], dim, nanFlagCell{:}, precisionFlagCell{:}), arg1); end out.Adaptor = outAdaptor; case 'ReduceInDefaultDim' outPA = reduceInDefaultDim(@(x, dim) fcn(x, [], dim, ... nanFlagCell{:}, precisionFlagCell{:}), arg1); out = tall(outPA, outAdaptor); otherwise assert(false, 'Unexpected reduction case.'); end end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function adaptor = iDeriveComparisonAdaptor(arg1, arg2) % Here we must be careful to consider that arg1 and arg2 aren't necessarily both % tall. adaptor1 = matlab.bigdata.internal.adaptors.getAdaptor(arg1); adaptor2 = matlab.bigdata.internal.adaptors.getAdaptor(arg2); if isequal(adaptor1.Class, adaptor2.Class) && ~isempty(adaptor1.Class) % Same - pick one, remembering that the size can be influenced by singleton % expansion. adaptor = resetSizeInformation(adaptor1); elseif isempty(adaptor1.Class) && isempty(adaptor2.Class) % Both empty - default to generic. adaptor = matlab.bigdata.internal.adaptors.GenericAdaptor(); else % Got some information. In this case, we need to propagate % datetime/duration/calendarDuration. We preferentially pick the first % adaptor. timeClasses = {'datetime', 'duration', 'calendarDuration'}; if ismember(adaptor1.Class, timeClasses) adaptor = resetSizeInformation(adaptor1); elseif ismember(adaptor2.Class, timeClasses) adaptor = resetSizeInformation(adaptor2); elseif strcmp(adaptor1.Class, 'categorical') % Handle categoricals: if either is categorical, copy that adaptor. adaptor = resetSizeInformation(adaptor1); elseif strcmp(adaptor2.Class, 'categorical') adaptor = resetSizeInformation(adaptor2); else % Don't know how to combine classes. This might result in a run-time error. adaptor = matlab.bigdata.internal.adaptors.GenericAdaptor(); end end end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function adaptor = iDeriveReduceInDefaultDimAdaptor(arg1) tmp = iConvertCharAdaptorsToDouble(arg1.Adaptor); % We might one day add size information here. adaptor = resetSizeInformation(tmp); end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function adaptor = iDeriveReduceInDimAdaptor(arg1, dim) tmp = iConvertCharAdaptorsToDouble(arg1.Adaptor); % Update the reduced dimension in the adaptor allowEmpty = true; adaptor = computeReducedSize(tmp, arg1.Adaptor, dim, allowEmpty); end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % min/max on char data always returns double. All other types are preserved. function newAdaptor = iConvertCharAdaptorsToDouble(oldAdaptor) if strcmp(oldAdaptor.Class, 'char') newAdaptor = matlab.bigdata.internal.adaptors.getAdaptorForType('double'); newAdaptor = copySizeInformation(newAdaptor, oldAdaptor); else newAdaptor = oldAdaptor; end end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [arg1, arg2] = iCheckAtLeastOneTallAndBroadcast(fcn, arg1, arg2) if ~istall(arg1) arg1 = matlab.bigdata.internal.broadcast(arg1); end if ~istall(arg2) arg2 = matlab.bigdata.internal.broadcast(arg2); end if ~istall(arg1) && ~istall(arg2) error(message('MATLAB:bigdata:array:MinMaxCompareTallData', fcn)) end end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function tf = iIsSmallEmpty(arg) % Check for a non-tall empty array tf = ~istall(arg) && isempty(arg); end