gusucode.com > symbolic工具箱matlab源码程序 > symbolic/@symfun/symfun.m

    classdef (InferiorClasses={?sym}) symfun < sym
    %SYMFUN   Symbolic function
    %   F = SYMFUN(FORMULA,INPUTS) returns a symbolic function
    %   with inputs INPUTS and body FORMULA. INPUTS must be a
    %   sym array of symbolic variables and FORMULA is a
    %   sym object expression.
    %
    %   Symbolic functions can represent both abstract functions
    %   as well as functions with a definition. To represent
    %   an abstract function use a formula like 'f(x)'.
    %
    %   The SYMS function and subscripted assignment provide a
    %   convenient syntax for defining symbolic functions.
    %
    %   Examples:
    %    syms f x y
    %    f = symfun(x+y, [x y])
    %    f(1,2)                 % returns 3
    %
    %    syms z(s,t)
    %    z(s,t) = s+t;
    %    f(s,t) - z(s,t)        % returns 0
    %
    %   See also SYMS, SYM/ARGNAMES, SYM/FORMULA, DSOLVE

    %   Copyright 2011-2015 The MathWorks, Inc.
    
    properties (Access=private)
        vars;
    end
    methods(Hidden,Static)
        function [name, vars] = parseString(x)
            % given a string f(arg1, arg2, .., argn)
            % returns f as a string,
            % and [arg1, ..., argn] as cell array of sym
            pos = find(x=='(',1)-1;
            if isempty(pos)
                % no function call.
                % The user must write sym('x') instead of 'x'
                error(message('symbolic:symfun:SymExpected'));
            end
            name = x(1:pos);
            closingPos = find(x==')', 1);
            varnamelist = x(pos+2:closingPos-1);
            reVarname = '[A-Za-z]\w*';
            if ~isvarname(name) || sym.isMathematicalConstant(name)|| ...
                    isempty(closingPos) || closingPos < length(x) || ...
                    any(ismember('[{', x)) || ...
                    isempty(regexp(varnamelist,['^\s*' reVarname '\s*(,\s*' reVarname '\s*)*$'],'once'))
                error(message('symbolic:sym:errmsg1'));
            end
            varnames = regexp(varnamelist, reVarname, 'match');
            vars = cellfun(@sym,varnames,'UniformOutput',false);
        end
    end
    methods
        function y = symfun(x,inputs)
            if isnumeric(x) 
                x = sym(x);
            elseif ischar(x)
               % string input must be of the form f(arg1, ..., argN)
               [name, vars] = symfun.parseString(x);
               x = feval(symengine, 'fp::apply', sym(name), vars{:});   
            elseif ~isa(x,'sym') 
                error(message('symbolic:symfun:SymExpected'));
            end 
            y = y@sym(formula(x));
            
            % check variables are simple names
            y.vars = validateArgNames(inputs);
        end

        function y = argnames(x)
            %ARGNAMES   Symbolic function input variables
            %   ARGNAMES(F) returns a sym array [X1, X2, ... ] of symbolic
            %   variables for F(X1, X2, ...).
            %
            %   Example
            %    syms f(x,y)
            %    argnames(f)    % returns [x, y]
            %
            %   See also SYMFUN/FORMULA
            y = x.vars;
        end

        function y = formula(x)
            %FORMULA   Symbolic function formula body
            %   FORMULA(F) returns the definition of symbolic
            %   function F as a sym object expression.
            %
            %   Examples:
            %    syms f(x,y)
            %    f(x,y) = x+y;
            %    formula(f)    % returns x+y
            %
            %    syms y(x)
            %    formula(y)    % returns y(x)
            %
            %   See also SYMFUN/ARGNAMES

            y = sym(mupadmex(x.s,11));
        end

        function c = isequal(a,b,varargin)
        %ISEQUAL     Symbolic function isequal test.
        %   ISEQUAL(A,B) returns true iff A and B are identical.
            
        if ~isa(a,'symfun') || ~isa(b,'symfun') || ~isequal(a.vars, b.vars)
            c = false;
        else
            mupc = mupadmex('symobj::isequal', a.s, b.s, 0);
            c = strcmp(mupc,'TRUE');
            if c && nargin > 2 
                c = isequal(b,varargin{:});
            end
        end
        end

        function c = isequaln(a,b,varargin)
        %ISEQUALN     Symbolic function isequal test.
        %   ISEQUALN(A,B) returns true iff A and B are identical treating
        %                 NaNs as equal.
            
        if ~isa(a,'symfun') || ~isa(b,'symfun') || ~isequal(a.vars, b.vars)
            c = false;
        else
            mupc = mupadmex('symobj::isequaln', a.s, b.s, 0);
            c = strcmp(mupc,'TRUE');
            if c && nargin > 2 
                c = isequaln(b,varargin{:});
            end
        end
        end
        
    end
    methods (Hidden=true)

        function Y = sym(X, ~, ~)
            if nargin > 1
                error(message('symbolic:symfun:NoAdditionalArguments'))
            end
            Y = X;
        end
        
        function delete(~)
        end
        
        function varargout = subsindex(varargin)  %#ok<STOUT>
            error(message('symbolic:symfun:subsindex'))
        end

        function B = subsref(A,S)
        %SUBSREF Subscripted reference for a sym array. 
        %     B = SUBSREF(A,S) is called for the syntax A(I).  S is a structure array
        %     with the fields:
        %         type -- string containing '()' specifying the subscript type.
        %                 Only parenthesis subscripting is allowed.
        %         subs -- Cell array or string containing the actual subscripts.
        %
        %   See also SYM.
            if builtin('numel',A) ~= 1,  A = normalizesym(A);  end
            if length(S)>1
                error(message('symbolic:sym:NestedIndex'));
            end
            if strcmp(S.type,'()')
                Avars = A.vars;
                inds = S.subs;
                if length(inds) ~= length(Avars)
                    error(message('symbolic:symfun:subsref', length(Avars), length(inds)))
                end
                strs = cellfun(@ischar,inds);
                if any(strcmp(inds(strs),':'))
                    error(message('symbolic:symfun:subsrefColon'))
                end
                B = feval(A,inds{:});
            else
                error(message('symbolic:symfun:Indexing'));
            end
        end

        function C = privResolveOutput(C,A)
            C = symfun(C, A.vars);
        end
        
        function C = privResolveOutputAndDelete(C,A,x)
            if isa(A, 'symfun')
                fargs = privsubsref(A.vars, logical(A.vars ~= x));
                % if no variables are left, C remains a sym
                if ~isempty(fargs)
                    C = symfun(C, fargs);
                end    
            end    
        end

        function argout = privResolveArgs(varargin)
            sfun = [];
            argout = varargin;
            n = nargin;
            for k=1:n
                arg = varargin{k};
                if isa(arg,'symfun')
                    sfun = arg;
                    break
                end
            end
            fvars = sfun.vars;
            for k=1:n
                arg = varargin{k};
                if isa(arg,'sym') && builtin('numel',arg) ~= 1
                    argout{k} = normalizesym(arg);
                elseif ~isa(arg,'sym')
                    argout{k} = sym(arg);
                end
                if isa(arg,'symfun') && ~isequal(fvars,arg.vars)
                    error(message('symbolic:symfun:InputMatch'));
                else
                    argout{k} = symfun(argout{k},fvars);
                end
            end
        end

        function varargout = end(varargin) %#ok<STOUT>
            error(message('symbolic:symfun:EndNotImplemented'));
        end

        function c = cross(a,b,dim)
        %CROSS Vector cross product of symbolic functions.
        %   The cross function of Core MATLAB needs to be
        %   overloaded for symfun objects, because it 
        %   requires vectors of length 3. Symfuns, however,
        %   are scalar objects.

        %   Copyright 2014 The MathWorks, Inc.
            narginchk(2,3);
            if ~isa(a, 'sym') && ~isa(b, 'sym')
               % there must be a dim argument
               c = cross(a, b, double(dim));
               return;
            end
            args = privResolveArgs(a,b);
            if nargin == 2
               c = cross(formula(args{1}), formula(args{2}));
            else
               c = cross(formula(args{1}), formula(args{2}), double(dim));
            end
            c = privResolveOutput(c, args{1});
        end

    end
end

function args = validateArgNames(args)
%validateArgNames   When creating symfuns make sure the arguments are simple sym object names
% do not allow zero arguments
if ~isequal(class(args),'sym') || ~isvector(args) || isempty(args)
    error(message('symbolic:symfun:VarsExpected'))
end
args = args(:).'; % maybe we don't really want to allow f([x;y])=x+y, but currently we do ...
args2 = unique(args);
if length(args2) ~= length(args)
    error(message('symbolic:symfun:VarsExpected'))
end
for k=1:length(args)
    arg = args(k);
    if ~isvarname(char(arg)) || ...
            ~strcmp(mupadmex(['testtype(' charcmd(arg) ',Type::Indeterminate)'],0),'TRUE')
        error(message('symbolic:symfun:VarsExpected'))
    end
end
end