www.gusucode.com > bigdata 工具箱 matlab源码程序 > bigdata/+matlab/+bigdata/+internal/+adaptors/AbstractAdaptor.m

    %AbstractAdaptor Adaptor base class.
%   Each tall array instance holds a PartitionedArray and an Adaptor.  The
%   Adaptor is responsible for holding metadata relating to the PartitionedArray
%   that is known at the client. The Adaptor also is responsible for
%   implementing methods that depend on that metadata.
%
%   In practice, this means that the all Adaptor classes hold at least the
%   following information about the PartitionedArray:
%    - Class - the underlying class of the data, or '' if not known
%    - NDims - NDIMS for the underlying array, or NaN if not known
%    - Size  - when NDIMS is non-NaN, a 1xNDims vector of size information,
%              where any element might be NaN if it is not known.
%
%   The primary responsibility of the Adaptor class is to implement the various
%   forms of indexing supported by tall arrays. The tall array methods SUBSREF
%   and SUBSASGN perform simple analysis to determine which form of indexing is
%   being performed, and then invoke one of the subsref* or subsasgn* methods on
%   the Adaptor, passing the corresponding PartitionedArray to operate on.

% Copyright 2016 The MathWorks, Inc.
classdef (Abstract) AbstractAdaptor

    properties (SetAccess = 'immutable')
        % Modifying class post-construction is a bad idea since this might allow an
        % adaptor to be used for an inappropriate type.
        Class = '';
    end
    properties (SetAccess = 'protected')
        % Size only valid if NDims is non-NaN
        NDims = NaN;
    end
    properties (Dependent)
        Size
        TallSizeId
    end
    
    properties (SetAccess = 'private')
        % TallSize is a handle to an object that can be shared by many Adaptors and thus
        % allows sizes to be injected.
        TallSize;
        % SmallSizes is a standard numeric array.
        SmallSizes = [];
    end
    
    methods
        function sz = get.Size(obj)
            if isnan(obj.NDims)
                sz = [];
            else
                sz = [obj.TallSize.Size, obj.SmallSizes];
            end
        end
        function tid = get.TallSizeId(obj)
            tid = obj.TallSize.Id;
        end
    end
        

    methods (Abstract)
        %getProperties return a cellstr of property names
        names = getProperties(obj)

        %displayImpl Implementation of DISPLAY.
        % displayInfo is matlab.bigdata.internal.display.DisplayInfo.
        displayImpl(obj, displayInfo, pa)
        
        %Various subsref implementations.
        subsrefParens(obj, pa, szPa, S)
        subsasgnParens(obj, pa, szPa, S, b)
        subsasgnParensDeleting(obj, pa, szPa, S)
        subsrefBraces(obj, pa, szPa, S)
        subsasgnBraces(obj, pa, szPa, S, b)
    end

    methods
        function varargout = subsrefDot(obj, pa, szPa, S) %#ok<INUSD,STOUT>
            error(message('MATLAB:structRefFromNonStruct'));
        end
        function obj = subsasgnDotDeleting(obj, pa, szPa, S) %#ok<INUSD>
            error(message('MATLAB:structAssToNonStruct'));
        end
        function obj = subsasgnDot(obj, pa, szPa, S, b) %#ok<INUSD>
            error(message('MATLAB:structAssToNonStruct'));
        end

        % For various reductions - convert strings into "missing" flags and "precision"
        % flags. Each return must be a cell array to enable forwarding of flags.
        function [nanFlagCell, precisionFlagCell] = interpretReductionFlags(obj, FCN_NAME, ~) %#ok<STOUT>
            error(message('MATLAB:bigdata:array:FcnNotSupportedForType', FCN_NAME, obj.Class));
        end
    end

    methods
        
        function obj = AbstractAdaptor(clz, tsz)
            obj.Class = clz;
            if nargin < 2
                obj.TallSize = matlab.bigdata.internal.adaptors.TallSize();
            else
                obj.TallSize = tsz;
            end
        end

        function tf = isSizeKnown(obj, optIdx)
        %isSizeKnown Call this to find out if the size of the tall is known
        %isSizeKnown(idx) checks whether one specific size entry is known
            if nargin>1
                tf = ~isnan(obj.getSizeInDim(optIdx));
            else
                tf = ~isnan(obj.NDims) && ~any(isnan(obj.Size));
            end
        end

        function sz = getSizeInDim(obj, dim)
        % Return the size of the array in the specified dimension
        % Will be nan for unknown dimensions.
            if dim <= length(obj.Size)
                % Part of the size vector
                sz = obj.Size(dim);
            else
                % Trailing dimension. If we know the number of
                % dimensions then this is definitely 1. Otherwise
                % unknown.
                if isnan(obj.NDims)
                    sz = nan;
                else
                    sz = 1;
                end
            end
        end
        
        function obj = setSizeInDim(obj, dim, sz)
        % Set the size of the array in the specified dimension.
        % Note that this will create a new tall size rather than updating
        % the tall size of existing arrays.
        assert(nargout==1);
        if dim==1
            obj.TallSize   = matlab.bigdata.internal.adaptors.TallSize(sz);      
            
        elseif ~isnan(obj.NDims)
            % Only set a small size if ndims is known. We may relax this
            % constraint later. We may need to extend the size vector.
            dim = dim - 1;
            if dim > length(obj.SmallSizes)
                % pad with trailing ones
                n = dim - length(obj.SmallSizes);
                obj.SmallSizes = [obj.SmallSizes, ones(1,n)];
            end
            obj.SmallSizes(dim) = sz;
            % Make sure the dimensions are still consistent
            obj = packDims(obj);
                
        end
        end
        
        function obj = setKnownSize(obj, szVec)
        %setKnownSize Call this when you know the size of the tall

            szVec = iFixSizeVector(szVec);
            nd = numel(szVec);
            assert(isnan(obj.NDims) || obj.NDims == nd);
            obj.NDims = numel(szVec);
            if isnan(szVec(1))
                obj.TallSize = matlab.bigdata.internal.adaptors.TallSize();
            else
                obj.TallSize.Size = szVec(1);
            end
            obj.SmallSizes = szVec(2:end);
            % Make sure the dimensions are still consistent
            obj = packDims(obj);
        end
        
        function obj = setSmallSizes(obj, smallSizes)
        %setSmallSizes Call this when the tall size is unchanged, and now you know the
        %small sizes
            
        % Note iFixSizeVector wants to work on a full size vector, so we prepend a dummy
        % NaN, and then strip it out again.
            if ~isnan(obj.NDims)
                assert(obj.NDims == 1 + numel(smallSizes));
                assert(all(obj.SmallSizes(~isnan(obj.SmallSizes)) == smallSizes(~isnan(obj.SmallSizes))));
            end
            tmp = iFixSizeVector([NaN smallSizes]);
            obj.SmallSizes = tmp(2:end);
            obj.NDims = numel(obj.SmallSizes) + 1;
        end
        
        function obj = resetSizeInformation(obj)
        %resetSizeInformation Call this when an operation has been performed that means
        %that all size information is lost
            obj.NDims      = NaN;
            obj.TallSize   = matlab.bigdata.internal.adaptors.TallSize();
            obj.SmallSizes = [];
        end
        
        function obj = resetTallSize(obj, m)
        %resetTallSize Call this when an operation has been performed that
        %changes the tall size but leaves other dimensions alone. Note that
        %this will update the tall size for all linked adaptors.
        %
        % ad = resetTallSize(ad) indicates unknown tall size (nan)
        % ad = resetTallSize(ad,m) sets the tall size to 'm'
            if nargin<2 || isnan(m)
                % Reset to unknown
                obj.TallSize = matlab.bigdata.internal.adaptors.TallSize();
            else
                obj.TallSize.Size = m;
            end
        end
        
        function obj = resetSmallSizes(obj, szVec)
        %resetSmallSizes Call this when an operation has been performed that
        %changes the small sizes but leaves the tall dimension alone (i.e.
        %slicefun)
        %
        % ad = resetSmallSizes(ad) indicates unknown small sizes (ndims = nan)
        % ad = resetSmallSizes(ad,szVec) sets the small sizes to szVec
        % (ndims = numel(szVec)+1)
            if nargin<2
                obj.NDims = NaN;
                obj.SmallSizes = [];
            else
                obj.NDims = numel(szVec)+1;
                obj.SmallSizes = szVec;
            end
        end
        
        function obj = copyTallSize(obj, copyFrom)
        % Call this when two arrays are guaranteed to have the same tall size. This
        % updates obj to use the same handle for 'TallSize'.
            obj.TallSize = copyFrom.TallSize;
        end
        
        function obj = copySizeInformation(obj, copyFrom)
        %copySizeInformation Call this to copy size information from one adaptor to
        %another.

            if isnan(copyFrom.NDims)
                % If copyFrom doesn't have small dimensions, reset everything
                obj = resetSizeInformation(obj);
            else
                obj.NDims      = copyFrom.NDims;
                obj.SmallSizes = copyFrom.SmallSizes;
            end

            % Always sync the tall sizes.
            obj = copyTallSize(obj, copyFrom);
        end
    end
    
    methods (Access=private)
        function obj = packDims(obj)
            % Helper to make sure we don't keep trailing ones in the small
            % sizes.
            if length(obj.SmallSizes) > 1
                lastNonTrivialDim = find(obj.SmallSizes(2:end) ~= 1, 1, 'last');
                if isempty(lastNonTrivialDim)
                    obj.SmallSizes = obj.SmallSizes(1);
                else
                    obj.SmallSizes = obj.SmallSizes(1:(1 + lastNonTrivialDim));
                end
                % Be careful about the trailing dim being NaN, since that
                % means it might be one (and hence ndims is not what we
                % think it is).
                if length(obj.SmallSizes)>1 && isnan(obj.SmallSizes(end))
                    % Since we can no longer guarantee the dimensionality,
                    % set ndims to nan.
                    obj.NDims = nan;
                else
                    obj.NDims = length(obj.SmallSizes)+1;
                end
            end
        end
    end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function szVec = iFixSizeVector(szVec)
% We insist on 'isfloat' for specifying sizes because otherwise NaN values
% get converted to zeros.
    assert(isrow(szVec) && numel(szVec) >= 2 && isfloat(szVec), ...
        'Specified size vector must be a row of floats with at least 2 elements.');
    lastNonTrivialDim = find(szVec(2:end) ~= 1, 1, 'last');
    if isempty(lastNonTrivialDim)
        szVec = szVec(1:2);
    else
        szVec = szVec(1:(1 + lastNonTrivialDim));
    end
end