www.gusucode.com > mbc 工具箱 matlab 源码程序 > mbc/@mbcinline/mbcinline.m

    classdef (Hidden,Sealed) mbcinline
    % MBCINLINE replacement version of inline using anonymous functions
    %     mbcinline expressions are vectorized unless explicitly devectorized
    %     using the devectorize method

    %  Copyright 2011-2015 The MathWorks, Inc. 
    
    properties(SetAccess=private)
        %INPUTS list of inputs
        Inputs = {};
        %EXPRESSION expression to evaluate
        Expression
    end
    
    properties (Access=private)
        %FHANDLE anonymous function handle for evaluation expression
       fHandle 
       %VERSION object version
       Version    = 2;
    end
    
    methods 
        function obj=mbcinline(varargin)
            %MBCINLINE Construct MBCINLINE object.
            %   MBCINLINE(EXPR) constructs an mbcinline function object from the
            %   MATLAB expression contained in the string EXPR.  The input
            %   arguments are automatically determined by searching EXPR
            %   for variable names (see SYMVAR). 
            %
            %   MBCINLINE(EXPR, ARG1, ARG2, ...) constructs an mbcinline
            %   function whose input arguments are specified by the
            %   strings ARG1, ARG2, ...  Multicharacter symbol names may
            %   be used.
            %
            %   Examples:
            %     g = mbcinline('t^2')
            %     g = mbcinline('sin(2*pi*f + theta)')
            %     g = mbcinline('sin(2*pi*f + theta)', 'f', 'theta')
            %     g = mbcinline('x^P1', 1)
            %
            %   See also SYMVAR.
            if nargin==1
                if isa(varargin{1},'mbcinline')
                    obj = varargin{1};
                    return
                else
                    if isa(varargin{1},'sym')
                        obj.Expression= char(varargin{1});
                    else
                        obj.Expression= varargin{1};
                    end
                    obj.Inputs = symvar(obj.Expression);
                    if ~iscell(obj.Inputs)
                        obj.Inputs = {obj.Inputs};
                    end
                end
            elseif nargin>1
               obj.Expression= varargin{1};
               if nargin==2 && iscell(varargin{2})
                   obj.Inputs = varargin{2};
               else
                   obj.Inputs = varargin(2:end);
               end 
               % make sure Inputs is a column vector
               obj.Inputs=obj.Inputs(:);
            end
            % vectorize expression 
            obj.Expression = vectorize(obj.Expression);
            % make anonymous function representation
            obj = makeAnon(obj);
            
        end
       
        function a = argnames(obj)
            %ARGNAMES Argument names.
            %   ARGNAMES(FUN) returns the names of the input arguments of the
            %   MBCINLINE object FUN as a cell array of strings.
            
            a = obj.Inputs;
        end
        function e=char(obj)
            %CHAR Convert MBCINLINE object to character array.
            %   CHAR(FUN) returns the formula for the INLINE object FUN.
            %   This is the same as FORMULA(FUN).
            %
            %   See also MBCINLINE, MBCINLINE/FORMULA.
           e= obj.Expression; 
        end
        function e=formula(obj)
            %FORMULA Function formula.
            %   FORMULA(FUN) returns the formula for the INLINE object FUN.
            %
            %   See also MBCINLINE/ARGNAMES, MBCINLINE/CHAR.
            e= obj.Expression;
        end
        function e=exist(obj) %#ok<*MANU>
            %EXIST for INLINE objects
            %   EXIST(F) returns 1 when F is an MBCINLINE object.
            e= 1;
        end
        
        
        function obj = vectorize(obj)
            %VECTORIZE vectorize expression 
            %  replace *, /, \, ^ with .*, ./ , .\, .^
            obj=mbcinline( vectorize(obj.Expression),obj.Inputs);
        end
        
        function s= sym(obj)
           obj = devectorize(obj);
           s = evalin(symengine, obj.Expression);
        end
        
        function obj = devectorize(obj)
            %DEVECTORIZE undoes vectorize
            %
            % gstr = devectorize(gstr)

            
            % SYM doesn't support .^,.*,./  operators
            gstr = obj.Expression;
            gstr= strrep(gstr,'.^','^');
            gstr= strrep(gstr,'.*','*');
            gstr= strrep(gstr,'./','/');
            gstr= strrep(gstr,'.\','\');
            
            % the constructor is not called as it vectorizes any expression
            obj.Expression = gstr;
            obj = makeAnon(obj);
        end
        
    end
    methods(Access=private)

        
        function obj = makeAnon(obj)
            %makeAnon make internal anonymous function from expression and
            %inputs
            
            if ~isempty(obj.Expression)
                try
                    obj.fHandle = str2func( sprintf('@(%s) %s',mbcListString(obj.Inputs),obj.Expression) );
                catch %#ok<CTCH>
                    % undefined expression
                    
                    % MBC makes checks elsewhere to ensure that the expression
                    % is evaluating correctly
                    obj.fHandle=[];
                end
            else
                obj.fHandle = [];
            end
            
        end
        
    end
    methods(Hidden)
        
        function varargout = subsref(obj,S)
           
            if length(S)==1 && strcmp(S.type,'()')
                [varargout{1:nargout}]=feval(obj,S.subs{:}); 
            else
                [varargout{1:nargout}]=builtin('subsref',obj,S); 
            end
                
        end
        

        
        function varargout = feval(obj,varargin)
            %FEVAL  FEVAL an INLINE object.
            
            
            % We only want to call the @inline/feval if the first argument is
            % actually an inline. Otherwise, defer to the builtin feval.
            if ~isa(obj, 'mbcinline')
                % If any of the elements in varargin are inline objects, then the
                %  overloaded inline feval is called even if the first argument
                %  is not an inline (such as a string or a function handle).
                %  In this case, we call the builtin feval.
                % varargout is needed here, although inline's only have one output,
                %  since it could have been called with any number of outputs.
                [varargout{1:nargout}] = builtin('feval',obj,varargin{:});
            else
                Ninputs = length(obj.Inputs);
                narginchk( Ninputs+1, Ninputs+1 );
                
                if (isempty(obj.fHandle))
                    y = [];
                else
                    % Need to evaluate expression in a function outside the @inline directory
                    % so that f(x), where f is an inline in the expression, will call the
                    % overloaded subsref.
                    y = obj.fHandle(varargin{:});
                end
                varargout{1} = y;
            end
        end
        
        function varargout = subsasgn(obj,S,New)
            error(message('mbc:mbcinline:subsasgn:notAllowed'));
        end
        function e=horzcat(varargin)
            error(message('mbc:mbcinline:horzcat:notAllowed'));
        end
        function e=vertcat(varargin)
            error(message('mbc:mbcinline:horzcat:notAllowed'));
        end
        function e=cat(varargin)
            error(message('mbc:mbcinline:horzcat:notAllowed'));
        end
            
        
        function n = nargout(obj)
            n = 1;
        end
        function n=nargin(obj)
           n = length(obj.Inputs); 
        end
        
    end
    
    methods (Static)
        function obj = loadobj(obj)
            if isstruct(obj) && isfield(obj,'inline')
                % load from old oops version which extended inline
                obj = mbcinline.convertFromInline(obj.inline);
            end
            
        end
        
        function obj = convertFromInline(obj)
            %convertFromInline convert inline object to mbcinline
            
            if isa(obj,'inline')
                obj = mbcinline(formula(obj),argnames(obj));
            elseif isstruct(obj)
                obj = mbcinline(obj.expr,obj.args);
            elseif ~isempty(obj)
                error(message('mbc:mbcinline:InvalidConversion', class( obj )))
            else
                % obj is empty and returned from convertFromInline
            end
            
        end
    end
    
end