www.gusucode.com > symbolic工具箱matlab源码程序 > symbolic/@sym/sym.m
classdef sym < handle %SYM Construct symbolic numbers, variables and objects. % S = SYM(A) constructs an object S, of class 'sym', from A. % If the input argument is a string, the result is a symbolic number % or variable. If the input argument is a numeric scalar or matrix, % the result is a symbolic representation of the given numeric values. % If the input is a function handle the result is the symbolic form % of the body of the function handle. % % x = sym('x') creates the symbolic variable with name 'x' and stores the % result in x. x = sym('x','real') also assumes that x is real, so that % conj(x) is equal to x. alpha = sym('alpha') and r = sym('Rho','real') % are other examples. Similarly, k = sym('k','positive') makes k a % positive (real) variable. x = sym('x','clear') restores x to a % formal variable with no additional properties (i.e., insures that x % is NEITHER real NOR positive). % See also: SYMS. % % A = sym('A',[N1 N2 ... Nk]) creates an N1-by-N2-...-by-Nk array of % symbolic scalar variables. Elements of vectors have names of the form Ai and elements % of matrices and higher-dimensional arrays have names of the form % Ai1_..._ik where each ij ranges over 1:Nj. % The form can be controlled exactly by using '%d' in the first % input (eg 'A%d%d' will make names Ai1i2). % A = sym('A',N) creates an N-by-N matrix. % sym(A,ASSUMPTION) makes or clears assumptions on A as described in % the previous paragraph. % % Statements like pi = sym('pi') and delta = sym('1/10') create symbolic % numbers which avoid the floating point approximations inherent in the % values of pi and 1/10. The pi created in this way temporarily replaces % the built-in numeric function with the same name. % % S = sym(A,flag) converts a numeric scalar or matrix to symbolic form. % The technique for converting floating point numbers is specified by % the optional second argument, which may be 'f', 'r', 'e' or 'd'. % The default is 'r'. % % 'f' stands for 'floating point'. All values are transformed from % double precision to exact numeric values N*2^e for integers N and e. % % 'r' stands for 'rational'. Floating point numbers obtained by % evaluating expressions of the form p/q, p*pi/q, sqrt(p/q), 2^q and 10^q % for modest sized integers p and q are converted to the corresponding % symbolic form. This effectively compensates for the roundoff error % involved in the original evaluation, but may not represent the floating % point value precisely. If no simple rational approximation can be % found, the 'f' form is used. % % 'e' stands for 'estimate error'. The 'r' form is supplemented by a % term involving the variable 'eps' which estimates the difference % between the theoretical rational expression and its actual floating % point value. For example, sym(3*pi/4,'e') is 3*pi/4-103*eps/249. % % 'd' stands for 'decimal'. The number of digits is taken from the % current setting of DIGITS used by VPA. Using fewer than 16 digits % reduces accuracy, while more than 16 digits may not be warranted. % For example, with digits(10), sym(4/3,'d') is 1.333333333, while % with digits(20), sym(4/3,'d') is 1.3333333333333332593, % which does not end in a string of 3's, but is an accurate decimal % representation of the double-precision floating point number nearest % to 4/3. % % See also SYMS, CLASS, DIGITS, VPA. % Copyright 1993-2015 The MathWorks, Inc. properties (Access=protected) s mathmlOutput end methods(Static) function y = loadobj(x) %LOADOBJ Load symbolic object % Y = LOADOBJ(X) is called when loading symbolic objects if isa(x,'struct') if isscalar(x) cx = {x.s}; else cx = reshape({x.s},size(x)); end y = cellfun(@(s) evalin(symengine, s), cx, 'UniformOutput', false); y = cell2sym(y); else n = builtin('numel',x); if n > 1 % x is an ndim sym cx = reshape({x.s},size(x)); y = cell2sym(cx); elseif n == 0 y = reshape(sym([]),size(x)); else y = x; end end end function y = zeros(varargin) %ZEROS Symbolic version of the builtin function ZEROS. y = sym(zeros(varargin{:})); end function y = ones(varargin) %ONES Symbolic version of the builtin function ONES. y = sym(ones(varargin{:})); end function y = empty(varargin) %EMPTY Symbolic version of the builtin function EMPTY. y = sym(double.empty(varargin{:})); end function y = inf(varargin) %INF Symbolic version of the builtin function INF. y = sym(inf(varargin{:})); end function y = nan(varargin) %NAN Symbolic version of the builtin function NAN. y = sym(nan(varargin{:})); end function y = eye(varargin) %EYE Symbolic version of the builtin function EYE. y = sym(eye(varargin{:})); end function y = cast(a) %CAST Symbolic version of the builtin function CAST. y = sym(a); end end methods(Hidden,Static) [eqns,vars] = getEqnsVars(varargin) B = checkIgnoreAnalyticConstraintsValue(v) B = isVariable(x) function B = isVariableName(x) B = isvarname(x) && ~isMathematicalConstant(x); end function B = isMathematicalConstant(x) B = any(strcmp(x, constantIdents)); end function B = isNumericString(x) % call local method B = isNumStr(x); end f = charToFunction(c) function res = useSymForNumeric(fn, varargin) for i = 1:nargin-1 if ~isnumeric(varargin{i}) error(message('symbolic:symbolic:NonNumericParameter')); end end oldDigits = digits(16); args = cellfun(@(x)vpa(x), varargin, 'UniformOutput', false); cleanupObj = onCleanup(@() digits(oldDigits)); res = cast(fn(args{:}),superiorfloat(varargin{:})); end function B = pathToFullPath(file) validateattributes(file, {'char'}, {'row'}); if java.io.File.isAbsolute(java.io.File(file)) B = file; else B = fullfile(pwd,file); end B = char(java.io.File.getCanonicalPath(java.io.File(B))); end end methods function S = sym(x, n, a) [~] = symengine; switch nargin case 0 S.s = '0'; case 1 S.s = tomupad(x); case 2 if (isnumeric(x) || islogical(x)) && ischar(n) % n is a flag S.s = tomupadWithFlag(x, n); elseif ischar(n) % n is an assumption % if x is a sym, instead of sym(x, set), % assume(x, set) has to be used if isa(x, 'sym') error(message('symbolic:sym:sym:UseAssume')); end S.s = tomupad(x); assume(S, n); elseif isnumeric(n) % n is a size S.s = tomupadWithSize(x, n); else error(message('symbolic:sym:SecondInputClass')); end otherwise % three arguments if ~isnumeric(n) error(message('symbolic:sym:SecondArgumentSizeVector')) end S.s = tomupadWithSize(x, n); assume(S, a); end % switch end % sym constructor function delete(h) if builtin('numel',h)==1 && inmem('-isloaded','mupadmex') && ... ~isempty(h.s) mupadmex(h.s,1); end end function y = argnames(~) %ARGNAMES Symbolic function input variables % ARGNAMES(F) returns a sym array [X1, X2, ... ] of symbolic % variables for F(X1, X2, ...). y = sym([]); end function x = formula(x) %FORMULA Symbolic function formula body % FORMULA(F) returns the definition of symbolic % function F as a sym object expression. % % FORMULA is a no-op on a sym. % See SYMFUN/FORMULA for the nontrivial operation. % % See also SYMFUN/ARGNAMES, SYMFUN/FORMULA end function y = length(x) %LENGTH Length of symbolic vector. % LENGTH(X) returns the length of vector X. It is equivalent % to MAX(SIZE(X)) for non-empty arrays and 0 for empty ones. % % See also NUMEL. xsym = privResolveArgs(x); x = xsym{1}; sz = size(x); if prod(sz)==0 y = 0; else y = max(sz); end end %--------------- Arithmetic ----------------- function Y = uminus(X) %UMINUS Symbolic negation. Y = privUnaryOp(X, 'symobj::map', '_negate'); end function Y = uplus(X) %UPLUS Unary plus. Xsym = privResolveArgs(X); X = Xsym{1}; Y = X; end function X = times(A, B) %TIMES Symbolic array multiplication. % TIMES(A,B) overloads symbolic A .* B. X = privBinaryOp(A, B, 'symobj::zip', '_mult'); end function X = mtimes(A, B) %TIMES Symbolic matrix multiplication. % MTIMES(A,B) overloads symbolic A * B. X = privBinaryOp(A, B, 'symobj::mtimes'); end function B = mpower(A,p) %POWER Symbolic matrix power. % POWER(A,p) overloads symbolic A^p. % % Example; % A = [x y; alpha 2] % A^2 returns [x^2+alpha*y x*y+2*y; alpha*x+2*alpha alpha*y+4]. B = privBinaryOp(A, p, 'symobj::mpower'); end function B = power(A,p) %POWER Symbolic array power. % POWER(A,p) overloads symbolic A.^p. % % Examples: % A = [x 10 y; alpha 2 5]; % A .^ 2 returns [x^2 100 y^2; alpha^2 4 25]. % A .^ x returns [x^x 10^x y^x; alpha^x 2^x 5^x]. % A .^ A returns [x^x 1.0000e+10 y^y; alpha^alpha 4 3125]. % A .^ [1 2 3; 4 5 6] returns [x 100 y^3; alpha^4 32 15625]. % A .^ magic(3) is an error. B = privBinaryOp(A, p, 'symobj::zip', '_power'); end function X = rdivide(A, B) %RDIVIDE Symbolic array right division. % RDIVIDE(A,B) overloads symbolic A ./ B. % % See also SYM/LDIVIDE, SYM/MRDIVIDE, SYM/MLDIVIDE, SYM/QUOREM. X = privBinaryOp(A, B, 'symobj::zip', 'symobj::divide'); end function X = ldivide(A, B) %LDIVIDE Symbolic array left division. % LDIVIDE(A,B) overloads symbolic A .\ B. % % See also SYM/RDIVIDE, SYM/MRDIVIDE, SYM/MLDIVIDE, SYM/QUOREM. X = privBinaryOp(B, A, 'symobj::zip', 'symobj::divide'); end function X = mrdivide(A, B) %/ Slash or symbolic right matrix divide. % A/B is the matrix division of B into A, which is roughly the % same as A*INV(B) , except it is computed in a different way. % More precisely, A/B = (B'\A')'. See SYM/MLDIVIDE for details. % Warning messages are produced if X does not exist or is not unique. % Rectangular matrices A are allowed, but the equations must be % consistent; a least squares solution is not computed. % % See also SYM/MLDIVIDE, SYM/RDIVIDE, SYM/LDIVIDE, SYM/QUOREM. X = privBinaryOp(A, B, 'symobj::mrdivide'); end function X = mldivide(A, B) %MLDIVIDE Symbolic matrix left division. % MLDIVIDE(A,B) overloads symbolic A \ B. % X = A\B solves the symbolic linear equations A*X = B. % Warning messages are produced if X does not exist or is not unique. % Rectangular matrices A are allowed, but the equations must be % consistent; a least squares solution is not computed. % % See also SYM/MRDIVIDE, SYM/LDIVIDE, SYM/RDIVIDE, SYM/QUOREM. X = privBinaryOp(A, B, 'symobj::mldivide'); end %--------------- Logical Operators ----------------- function X = eq(A, B) %EQ Symbolic equality test. % EQ(A,B) overloads symbolic A == B. If A and B are integers, % rational numbers, floating point values or complex numbers % then A == B compares the values and returns true or false. % Otherwise A == B returns a sym object of the unevaluated equation % which can be passed to other functions like solve. To force % the equation to perform a comparison call LOGICAL or isAlways. % LOGICAL will compare the two sides structurally. isAlways will % compare the two sides mathematically. % % See also SYM/LOGICAL, SYM/isAlways try X = privComparison(A, B, '_equal', 'FALSE', 'FALSE'); catch resSize = size(A); if isscalar(A) resSize = size(B); elseif ~isscalar(B) && ~isequal(size(A), size(B)) error(message('MATLAB:dimagree')); end X = sym(zeros(resSize)) == sym(ones(resSize)); end end function X = ne(A, B) %NE Symbolic inequality test. % NE(A,B) overloads symbolic A ~= B. The result is the opposite of % A == B. X = privComparison(A, B, '_unequal', 'FALSE', 'TRUE'); end function X = logical(A) %LOGICAL Convert symbolic expression to logical array % Y = LOGICAL(X) converts each element of the symbolic % array X into the value true or false. % Symbolic equations are converted to true % only if the left and right sides are identically % the same. Otherwise the equation is converted to % false. Inequalities which cannot be proved will % throw an error. % % See also: sym/isAlways if builtin('numel',A) ~= 1, A = normalizesym(A); end X = mupadmex('symobj::logical',A.s,9); end function X = all(A, dim) %ALL True if all symbolic values are true if nargin==1 X = all(logical(A)); else X = all(logical(A),double(dim)); end end function varargout = find(A,varargin) %FIND Find non-zero elements of symbolic arrays narginchk(1, 3); if nargin == 3 try varargin{2} = validatestring(varargin{2}, {'first','last'}); catch err error(message('MATLAB:find:InputClass')); end end if ~isa(A, 'sym') varargin{1} = double(varargin{1}); [varargout{1:nargout}] = find(A, varargin{:}); return end if builtin('numel',A) ~= 1, A = normalizesym(A); end B = mupadmex('symobj::find',A.s,9); if nargout == 3 [i,j] = find(B,varargin{:}); c = sym(i); if numel(formula(A)) == 1 if ~isempty(c) c = formula(A); end else for k = 1:length(i) c = privsubsasgn(c, privTrinaryOp(A, i(k), j(k), '_index'), k); end end varargout{1} = i; varargout{2} = j; varargout{3} = c; else [varargout{1:nargout}] = find(B,varargin{:}); end end function X = any(A, dim) %ANY True if any symbolic value is true if nargin==1 X = any(logical(A)); else X = any(logical(A),double(dim)); end end function c = isequal(a,b,varargin) %ISEQUAL Symbolic isequal test. % ISEQUAL(A,B) returns true iff A and B are identical. if ~isa(a, 'sym') || ~isa(b, 'sym') c = false; else args = privResolveArgs(a, b, varargin{:}); mupc = mupadmex('symobj::isequal', args{1}.s, args{2}.s, 0); c = strcmp(mupc,'TRUE'); end if c && nargin > 2 c = isequal(b,varargin{:}); end end function c = isequaln(a,b,varargin) %ISEQUALN Symbolic isequaln test. % ISEQUALN(A,B) returns true iff A and B are identical % treating NaNs as equal. if ~isa(a, 'sym') || ~isa(b, 'sym') c = false; else args = privResolveArgs(a, b, varargin{:}); mupc = mupadmex('symobj::isequaln', args{1}.s, args{2}.s, 0); c = strcmp(mupc,'TRUE'); end if c && nargin > 2 c = isequaln(b,varargin{:}); end end function X = gt(A,B) %GT Symbolic greater-than. X = privComparison(B, A, '_less', 'TRUE', 'FALSE'); end function X = lt(A,B) %LT Symbolic less-than. X = privComparison(A, B, '_less', 'TRUE', 'FALSE'); end function X = ge(A,B) %GE Symbolic greater-than-or-equal. X = privComparison(B, A, '_leequal', 'TRUE', 'FALSE'); end function X = le(A,B) %LE Symbolic less-than-or-equal. X = privComparison(A, B, '_leequal', 'TRUE', 'FALSE'); end function assume(cond,set) %ASSUME Assume symbolic relationship. % ASSUME(COND) sets the condition COND to be true. When you % set an assumption, the toolbox replaces any previous % assumptions on the free variables in COND with the new % assumption. % ASSUME(X,SET) assumes the variable X is in the specified % set. Specify SET as 'integer','rational', 'real', or 'positive'. % ASSUME(X,'CLEAR') removes the assumptions on X. % % % Example % syms x % assume(x > 1) % isAlways(sqrt(x^2) > 1) % returns true % assume(x,'clear') % removes assumptions % % See also SYM, SYM/assumeAlso,ASSUMPTIONS. if builtin('numel',cond) ~= 1, cond = normalizesym(cond); end if nargin == 2 S = validatestring(set, {'integer', 'rational', 'real', 'positive', 'clear'}); if strcmp(S, 'clear') feval(symengine, 'unassume', cond); else mset = setToMuPADSet(S); feval(symengine, 'assume', cond, mset); end else feval(symengine, 'assume', cond); end if ~isempty(cond) && isempty(symvar(cond)) && (nargin < 2 || ~strcmp(S, 'clear')) warning(message('symbolic:sym:sym:AssumptionsOnConstantsIgnored')); end end function assumeAlso(cond,set) %assumeAlso Add symbolic assumption. % assumeAlso(COND) sets the condition COND to be true % in addition to all previous assumptions. % assumeAlso(X,SET) assumes the variable X is in the specified % set. Specify SET as 'integer','rational', 'real', or 'positive'. % % Example % syms x y % assume(x < y) % assumeAlso(y > 0) % isAlways(x^2 >= y^2) % returns true % syms x y clear % removes assumptions % % See also SYM, SYM/ASSUME, ASSUMPTIONS. if builtin('numel',cond) ~= 1, cond = normalizesym(cond); end if nargin == 2 mset = setToMuPADSet(set); feval(symengine, 'assumeAlso', cond, mset); else feval(symengine, 'assumeAlso', cond); end if ~isempty(cond) && isempty(symvar(cond)) warning(message('symbolic:sym:sym:AssumptionsOnConstantsIgnored')); end end function X = and(A,B) %AND Symbolic & (and). X = privBinaryOp(A, B, 'symobj::zip', 'symobj::_and'); end function X = or(A,B) %OR Symbolic | (or). X = privBinaryOp(A, B, 'symobj::zip', 'symobj::_or'); end function X = xor(A,B) %XOR Symbolic exclusive-or. X = privBinaryOp(A, B, 'symobj::zip', 'symobj::_xor'); end function X = not(A) %NOT Symbolic ~ (not). X = privUnaryOp(A, 'symobj::map', '_not'); end function r = isreal(x) %ISREAL True for real symbolic array % ISREAL(X) returns true if X equals conj(X) and false otherwise. r = isequaln(x,conj(x)); end function y = isscalar(x) %ISSCALAR True if symbolic array is a scalar % ISSCALAR(S) returns logical true (1) if S is a 1 x 1 symbolic matrix % and logical false (0) otherwise. xsym = privResolveArgs(x); x = xsym{1}; y = numel(x)==1; end function y = isempty(x) %ISEMPTY True for empty symbolic array % ISEMPTY(X) returns 1 if X is an empty array and 0 otherwise. An % empty array has no elements, that is prod(size(X))==0. xsym = privResolveArgs(x); x = xsym{1}; y = numel(x)==0; end %--------------- Conversions ----------------- function X = double(S) %DOUBLE Converts symbolic matrix to MATLAB double. % DOUBLE(S) converts the symbolic matrix S to a matrix of double % precision floating point numbers. S must not contain any symbolic % variables, except 'eps'. % % See also SYM, VPA. if builtin('numel',S) ~= 1 S = normalizesym(S); end siz = size(formula(S)); Xstr = mupadmex('symobj::double', S.s, 0); X = eval(Xstr); if prod(siz) ~= 1 X = reshape(X,siz); end end function g = inline(f,varargin) %INLINE Generate an inline object from a sym object % % INLINE will be removed in a future release. Use anonymous % functions instead. % % G = INLINE(F) generates an inline object G from the symbolic % expression F using the matlabFunction sym method. % % See also: matlabFunction f = sym(f); if builtin('numel',f) ~= 1, f = normalizesym(f); end func = matlabFunction(f); c = func2str(func); paren = find(c==')',1); g = inline(c(paren+1:end),varargin{:}); %#ok<DINLN> end function S = single(X) %SINGLE Converts symbolic matrix to single precision. % SINGLE(S) converts the symbolic matrix S to a matrix of single % precision floating point numbers. S must not contain any symbolic % variables, except 'eps'. % % See also SYM, SYM/VPA, SYM/DOUBLE. S = single(double(X)); end function Y = int8(X) %INT8 Converts symbolic matrix to signed 8-bit integers. % INT8(S) converts a symbolic matrix S to a matrix of % signed 8-bit integers. % % See also SYM, VPA, SINGLE, DOUBLE, % INT16, INT32, INT64, UINT8, UINT16, UINT32, UINT64. Y = int8(int64(X)); end function Y = int16(X) %INT16 Converts symbolic matrix to signed 16-bit integers. % INT16(S) converts a symbolic matrix S to a matrix of % signed 16-bit integers. % % See also SYM, VPA, SINGLE, DOUBLE, % INT8, INT32, INT64, UINT8, UINT16, UINT32, UINT64. Y = int16(int64(X)); end function Y = int32(X) %INT32 Converts symbolic matrix to signed 32-bit integers. % INT32(S) converts a symbolic matrix S to a matrix of % signed 32-bit integers. % % See also SYM, VPA, SINGLE, DOUBLE, % INT8, INT16, INT64, UINT8, UINT16, UINT32, UINT64. Y = int32(int64(X)); end function Y = int64(X) %INT64 Converts symbolic matrix to signed 64-bit integers. % INT64(S) converts a symbolic matrix S to a matrix of % signed 64-bit integers. % % See also SYM, VPA, SINGLE, DOUBLE, % INT8, INT16, INT32, UINT8, UINT16, UINT32, UINT64. Xsym = privResolveArgs(X); X = Xsym{1}; siz = size(formula(X)); Xd = mupadmex('symobj::double', X.s); Xstr = mupadmex('symobj::map', Xd.s, 'round', 0); Y = eval(['int64(' Xstr ')']); if prod(siz) ~= 1 Y = reshape(Y,siz); end end function Y = uint8(X) %UINT8 Converts symbolic matrix to unsigned 8-bit integers. % UINT8(S) converts a symbolic matrix S to a matrix of % unsigned 8-bit integers. % % See also SYM, VPA, SINGLE, DOUBLE, % INT8, INT16, INT32, INT64, UINT16, UINT32, UINT64. Y = uint8(uint64(X)); end function Y = uint16(X) %UINT16 Converts symbolic matrix to unsigned 16-bit integers. % UINT16(S) converts a symbolic matrix S to a matrix of % unsigned 16-bit integers. % % See also SYM, VPA, SINGLE, DOUBLE, % INT8, INT16, INT32, INT64, UINT8, UINT32, UINT64. Y = uint16(uint64(X)); end function Y = uint32(X) %UINT32 Converts symbolic matrix to unsigned 32-bit integers. % UINT32(S) converts a symbolic matrix S to a matrix of % unsigned 32-bit integers. % % See also SYM, VPA, SINGLE, DOUBLE, % INT8, INT16, INT32, INT64, UINT8, UINT16, UINT64. Y = uint32(uint64(X)); end function Y = uint64(X) %UINT64 Converts symbolic matrix to unsigned 64-bit integers. % UINT64(S) converts a symbolic matrix S to a matrix of % unsigned 64-bit integers. % % See also SYM, VPA, SINGLE, DOUBLE, % INT8, INT16, INT32, INT64, UINT8, UINT16, UINT32. Xsym = privResolveArgs(X); X = Xsym{1}; siz = size(formula(X)); Xd = mupadmex('symobj::double', X.s); Xstr = mupadmex('symobj::map', Xd.s, 'round', 0); Y = eval(['uint64(' Xstr ')']); if prod(siz) ~= 1 Y = reshape(Y,siz); end end function Y = full(X) %FULL Create non-sparse array % Y = FULL(X) creates a full symbolic array from X. Y = X; end end % public methods methods (Hidden=true) %--------------- Indexing ----------------- function X = subsindex(A) %SUBSINDEX Symbolic subsindex function if builtin('numel',A) ~= 1, A = normalizesym(A); end kind = mupadmex('symobj::subsindex',A.s,0); if kind(2) == 'L' X = find(mupadmex('symobj::logical',A.s,9)) - 1; elseif kind(2) == 'D' || isempty(A) X = double(A) - 1; else error(message('symbolic:sym:subscript:InvalidIndexOrFunction')); end end function B = subsref(L,Idx) %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',L) ~= 1, L = normalizesym(L); end if length(Idx)>1 error(message('symbolic:sym:NestedIndex')); end warnNonInteger = false; % for consistency, no warning for A(-1.5) if strcmp(Idx.type,'()') && ~isempty(Idx.subs) && ... (isa(Idx.subs{1}, 'double') || isa(Idx.subs{1}, 'single')) subsval = round(Idx.subs{1}); if ~isequal(subsval, Idx.subs{1}) warnNonInteger = true; Idx.subs{1} = subsval; end end % special case shortcut for L(:) if strcmp(Idx.type,'()') && numel(Idx.subs)==1 && ... ischar(Idx.subs{1}) && strcmp(Idx.subs{1},':') B = reshape(L,[],1); return; end % shortcut for simple indexing R_tilde = Inf; if strcmp(Idx.type,'()') && ~isempty(Idx.subs) && ... all(cellfun(@(x) isscalar(x) && isnumeric(x) && ... x==round(x) && isfinite(x) && x > 0, Idx.subs)) if numel(Idx.subs) == 1 R_tilde = Idx.subs{1}; else R_tilde = sub2ind(size(L), Idx.subs{:}); end end if R_tilde > numel(L) L_tilde = reshape(1:numel(L),size(L)); R_tilde = builtin('subsref',L_tilde,Idx); end B = mupadmex('symobj::subsref',L.s,privformat(R_tilde)); if warnNonInteger warning(message('MATLAB:colon:nonIntegerIndex')); end end function y = end(x,varargin) %END Last index in an indexing expression for a sym array. % END(A,K,N) is called for indexing expressions involving the sym % array A when END is part of the K-th index out of N indices. For example, % the expression A(end-1,:) calls A's END method with END(A,1,2). % % See also SYM. xsym = privResolveArgs(x); x = xsym{1}; sz = size(x); k = varargin{1}; n = varargin{2}; if n < length(sz) && k==n sz(n) = prod(sz(n:end)); end if n > length(sz) sz = [sz ones(1, n-length(sz))]; end y = sz(k); end function C = subsasgn(L,Idx,R) %SUBSASGN Subscripted assignment for a sym array. % C = SUBSASGN(L,Idx,R) is called for the syntax L(Idx)=R. Idx 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 length(Idx)>1 error(message('symbolic:sym:NestedIndex')); end if ~strcmp(Idx.type,'()') error(message('symbolic:sym:InvalidIndexingAssignment')); end inds = Idx.subs; warnNonInteger = false; % for consistency, no warning for A(-1.5) dosubs = false; for k=1:length(inds) if isa(inds{k}, 'double') || isa(inds{k}, 'single') inds_round = round(inds{k}); if ~isequal(inds_round, inds{k}) warnNonInteger = true; inds{k} = inds_round; end end if isa(inds{k}, 'symfun') || isempty(inds{k}) || ~isAllVars(inds{k}) dosubs = true; end end if dosubs if isa(L, 'symfun') error(message('symbolic:sym:subscript:InvalidIndexOrFunction')); end C = privsubsasgn(L,R,inds{:}); else C = symfun(sym(R),[inds{:}]); end if warnNonInteger warning(message('MATLAB:colon:nonIntegerIndex')); end end function y = makeListOutOfMuPADSequences(x) y = mupadmex(['DOM_LIST(', x.s, ')']); end function [y,flag] = isNullObjOrSeq(x) %isNullObjOrSeq Test for null object or sequence % [y,flag] = isNullObjOrSeq(X) returns true if X is a sym object % for the MuPAD null object or the MuPAD sequence. In case y is % true, the second argument indicates whether X is the MuPAD % null object or a MuPAD sequence. In case y is false, the % return value for flag is the empty string. xsym = privResolveArgs(x); x = xsym{1}; str = mupadmex('type', x.s, 0); y = strcmp(str,'') || strcmp(str,'DOM_NULL'); if y == true flag = 'null()'; else y = strcmp(str,'"_exprseq"'); if y == true flag = 'sequence'; else flag = ' '; end end end function argout = privResolveArgs(varargin) argout = varargin; n = nargin; 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 end end function C = privResolveOutput(C,~) end function C = privResolveOutputAndDelete(C,~,~) end function C = privQuaternaryOp(A,B,C,D,op,varargin) args = privResolveArgs(A, B, C, D); Csym = mupadmex(op,args{1}.s, args{2}.s, args{3}.s, args{4}.s, varargin{:}); C = privResolveOutput(Csym, args{1}); end function C = privTrinaryOp(A,B,C,op,varargin) args = privResolveArgs(A, B, C); Csym = mupadmex(op,args{1}.s, args{2}.s, args{3}.s, varargin{:}); C = privResolveOutput(Csym, args{1}); end function C = privBinaryOp(A,B,op,varargin) args = privResolveArgs(A, B); Csym = mupadmex(op,args{1}.s, args{2}.s, varargin{:}); C = privResolveOutput(Csym, args{1}); end function B = privUnaryOp(A,op,varargin) args = privResolveArgs(A); Csym = mupadmex(op,args{1}.s,varargin{:}); B = privResolveOutput(Csym,A); end function X = privComparison(A,B,op,project,flipnan) args = privResolveArgs(A, B); [Xsym, ~] = mupadmexnout('symobj::eq', args{1}, args{2}.s, ... op, project, flipnan); X = privResolveOutput(Xsym, args{1}); end function M = charcmd(A) %CHARCMD Convert scalar or array sym to string command form % CHARCMD(A) converts A to its string representation for sending commands % to the symbolic engine. if builtin('numel',A) ~= 1, A = normalizesym(A); end M = A.s; end function varargout = mupadmexnout(fcn,varargin) %MUPADMEXNOUT % This is an undocumented function that may be removed in a future release. args = varargin; for k=1:nargin-1 arg = args{k}; if isa(arg,'sym') args{k} = arg.s; end end out = mupadmex(fcn,args{:}); varargout = cell(1,nargout); for k=1:nargout varargout{k} = mupadmex(sprintf('%s[%d]',out.s,k)); end end function B = privsubsref(L,varargin) %PRIVSUBSREF Private access to subsref % Y = PRIVSUBSREF(X,I1,I2,...) returns the subsref X(I1,I2,..). Methods % in the sym class can call this to avoid calling the builtin subsref. if builtin('numel',L) ~= 1, L = normalizesym(L); end L = formula(L); % shortcut for simple indexing R_tilde = Inf; if all(cellfun(@(x) isscalar(x) && isnumeric(x) && ... x==round(x) && isfinite(x) && x > 0, varargin)) if numel(varargin) == 1 R_tilde = varargin{1}; else R_tilde = sub2ind(size(L), varargin{:}); end end if R_tilde > numel(L) L_tilde = reshape(1:numel(L),size(L)); R_tilde = builtin('subsref',L_tilde,struct('type','()','subs',{varargin})); end B = mupadmex('symobj::subsref',L.s,privformat(R_tilde)); end function C = privsubsasgn(L, R, varargin) %PRIVSUBSASGN Private access to subsasgn % Y = PRIVSUBSASGN(X,B,I1,I2,...) returns the subsasgn X(I1,I2,..)=B. Methods % in the sym class can call this to avoid calling the builtin subsasgn. if ~isa(L,'sym') L = sym(L); end if builtin('numel',L) ~= 1, L = normalizesym(L); end if ~isa(R,'sym') R = sym(R); end if builtin('numel',R) ~= 1, R = normalizesym(R); end % sL = size(L); sL = eval(mupadmex('symobj::size', L.s, 0)); % sR = size(R); sR = eval(mupadmex('symobj::size', R.s, 0)); % shortcut for the most frequent case, A(2,2)=7, for performance reasons: if prod(sR) == 1 && ... numel(sL) == numel(varargin) && ... all(cellfun(@isnumeric, varargin)) && ... all(cellfun(@isscalar, varargin)) && ... all(cellfun(@isfinite, varargin)) && ... all([varargin{:}] <= sL) inds = sub2ind(sL, varargin{:}); new_size = strrep(mat2str(sL),' ',','); assign_pos = privformat([inds,-1]); else L_tilde = reshape(1:prod(sL),sL); R_tilde = -reshape(1:prod(sR),sR); L_tilde2 = builtin('subsasgn',L_tilde,struct('type','()','subs',{varargin}),R_tilde); % extract sparse pattern of what we need to assign new_size = strrep(mat2str(size(L_tilde2)),' ',','); if numel(L_tilde2) == 0 C = sym(L_tilde2); return; end if ~isequal(ndims(L_tilde), ndims(L_tilde2)) % we need to transmit all positions to assign to inds = 1:numel(L_tilde2); else if ~isequal(size(L_tilde), size(L_tilde2)) % we're interested in the part of L_tilde that has the same size as L_tilde2 % enlarge far enough that we can safely extract that: out_pos = num2cell(size(L_tilde2) + 1); % we're not going to look there L_tilde(out_pos{:}) = 0; sub_part = num2cell([size(L_tilde2), ones(ndims(L_tilde)-ndims(L_tilde2))]); sub_part = cellfun(@(n) 1:n,sub_part,'UniformOutput',false); L_tilde = L_tilde(sub_part{:}); end inds = find(L_tilde2 ~= L_tilde); L_tilde2 = L_tilde2(inds); end assign_pos = privformat([inds(:),L_tilde2(:)]); end if isempty(inds) && isequal(size(L_tilde), size(L_tilde2)) C = L; else C = mupadmex('symobj::subsasgn',L.s,R.s,new_size,assign_pos); end end function y = privToCell(x) y = arrayfun(@(t){t},x); end function y = normalizesym(x) %NORMALIZESYM Normalize an n-dim array sym to 9b semantics % Y = NORMALIZESYM(X) checks if X is an n-dim array loaded % from 9a mat file and converts it to a scalar ptr-to-array % value used in 9b. sz = builtin('size',x); P = prod(sz); if P == 0 y = reshape(sym([]),sz); elseif P == 1 % shortcut for the most frequent case y = x; else c = cell(sz); for k=1:prod(sz) c{k} = x(k).s; end y = cellfun(@(S) evalin(symengine, S), c, 'UniformOutput' , false); y = cell2sym(y); end end function ezhelper(fcn,f,varargin) %EZHELPER Helper function for ezmesh, ezmeshc and ezsurf % EZHELPER(FCN,F,...) turns sym object F into a function handle % and calls the regular ez-function FCN. % EZHELPER(FCN,X,Y,Z,...) turns sym objects X,Y,Z into a function handle % and calls the regular ez-function FCN. if (length(varargin) >= 2) && (isa(varargin{1},'sym') || isa(varargin{2},'sym')) y = varargin{1}; z = varargin{2}; vars = unique([symvar(f) symvar(y) symvar(z)]); F = matlabFunction(f,'vars',vars); Y = matlabFunction(y,'vars',vars); Z = matlabFunction(z,'vars',vars); checkNoSyms(varargin(3:end)); fcn(F,Y,Z,varargin{3:end}); title(texlabel(['x = ' char(f) ', y = ' char(y) ', z = ' char(z)])); else F = matlabFunction(f); checkNoSyms(varargin); fcn(F,varargin{:}); title(texlabel(char(f))); end end function code = generateCode(s,t,lang,varargin) %generateCode Helper function for code generation % generateCode(s,t,lang,varargin) generates code for lang for the expression % s with name t and further options in varargin. ps = inputParser; ps.addParameter('file','',@ischar); ps.parse(varargin{:}); opts = ps.Results; if isempty(t) t = 'T'; end arg = privResolveArgs(s); if ~isempty(opts.file) generateCodeFile(t,arg{1},lang,opts); code = []; else code = sprintf(mupadmex('symobj::generateCode', ['"' t '"'], ['"' lang '"'], arg{1}.s, 0)); code(code == '"') = []; code = deblank(code); end end function generateCodeFile(t,r,lang,opts) %generateCodeFile Helper function for code generation % generateCodeFile(t,r,lang,opts) generates code for lang for the expression r % with name t and options opts. if nargout > 0 error(message('symbolic:sym:generateCode:NoOutput')); end gent = mupadmex('symobj::optimize',r.s); file = opts.file; [fid,msg] = fopen(file,'wt'); if fid == -1 error(message('symbolic:sym:generateCode:FileError', file, msg)); end tmp = onCleanup(@()fclose(fid)); for k = 1:length(gent) expr = sprintf('%s[%d]',gent.s, k); tk = mupadmex('symobj::generateCode', ['"' t '"'], ['"' lang '"'], expr, 0); str = strtrim(sprintf(tk)); str(str == '"') = []; fprintf(fid,'%s',str); end end function createMathML(s) %CREATEMATHML Generate MathML presentation from sym object s. % mathML(s) generates MathML code for the expression s. % get the correct number of digits to display for symfuns: numbers = regexp(s.s, '^_symans_(\d+)', 'tokens'); if ~isempty(numbers) oldDigits = digits(numbers{1}{1}); resetDigits = onCleanup(@() digits(oldDigits)); end s.mathmlOutput = mupadmex('symobj::generateMathML',s.s, 0); end function str = mathML(s) %MATHML Return MathML presentation stored in sym object s. % mathML(s) retrieves MathML code for the expression s. if isempty(s.mathmlOutput) createMathML(s); end str = s.mathmlOutput; end end % private methods end % classdef %--------------- Subfunctions ----------------- function S = tomupad(x) %TOMUPAD Convert input to sym reference string % Called by sym constructor to take 'x' (just about anything) and return the reference string S. % This function is recursive % since it calls mupadmex and it can call back into sym with _symansNNN. % The reference string for simple variable names like 'x' or 'foo' is % the variable name (with possible _Var appended). If 'a' is a size vector % then a vector or matrix symbolic variable is constructed. if isa(x,'function_handle') x = funchandle2ref(x); end % avoid conversion to double for large integers that lose precision there: if isa(x,'char') if ~isempty(x) && x(1)=='_' % answer from mupadmex _symansNNN S = x; else S = convertChar(x); end elseif isnumeric(x) || islogical(x) S = cell2ref(numeric2cellstr(x)); elseif isa(x,'sym') xsym = privResolveArgs(x); x = xsym{1}; S = mupadmex(x.s,11); % make a new reference elseif iscell(x) % undocumented syntax, still allowed for compatibility reasons xsym = cell2sym(x); S = mupadmex(xsym.s,11); % make a new reference else error(message('symbolic:sym:sym:errmsg7', class( x ))) end end function S = tomupadWithSize(x,n) S = createCharMatrix(x, n); end function S = tomupadWithFlag(x,a) S = cell2ref(numeric2cellstr(x, a)); end function S = numeric2cellstr(x,a) %NUMERIC2CELLSTR Convert numeric array to cell of strings. % converts a numeric array x into a cell string array of % the same size but with each element the string form of the corresponding % numeric element. The input 'a' determines the form of the conversion. S = cell(size(x)); if nargin == 1 a = 'r'; elseif strcmpi(a,'d') digs = digits; end for k = 1:numel(x) if isinteger(x(k)) S{k} = symInt2Str(x(k)); else switch lower(a) case 'f' S{k} = symf(double(x(k))); case 'r' S{k} = symr(double(x(k))); case 'e' S{k} = syme(double(x(k))); case 'd' S{k} = symd(double(x(k)),digs); otherwise error(message('symbolic:sym:sym:errmsg6')); end end end end function S = cell2ref(x) %CELL2REF Convert cell array x into a MuPAD reference string S % x can be a cell array of strings or sym objects y = x; if ~iscellstr(x) y = tocellstr(x); end S = mupadmex(y); end function y = tocellstr(x) %TOCELLSTR Convert sym objects in cell array x into reference string. y = x; for k=1:numel(x) if isa(x{k},'sym') y{k} = x{k}.s; end end end function S = funchandle2ref(x) %FUNCHANDLE2REF convert func handle x to string form str = char(x); ind1 = find(str == '(',1); if isempty(ind1) && nargin(x) >= 1 % This is the case for most non-anonymous function handles, % e.g, @sin. error(message('symbolic:sym:sym:FunctionMustBeAnonymous')); end ind2 = find(str == ')',1); inputs = str(ind1+1:ind2-1); if ~isempty(inputs) S = regexp(inputs, ',', 'split'); S = cellfun(@sym, S, 'UniformOutput', false); S = x(S{:}); else S = sym(x()); end end function S = symf(x) %SYMF Hexadecimal symbolic representation of floating point numbers. if imag(x) > 0 S = ['(' symf(real(x)) ')+(' symf(imag(x)) ')*1i']; elseif imag(x) < 0 S = ['(' symf(real(x)) ')-(' symf(abs(imag(x))) ')*1i']; elseif isinf(x) if x > 0 S = 'Inf'; else S = '-Inf'; end elseif isnan(x) S = 'NaN'; elseif x == 0 S = '0'; else S = symfl(x); end end function [S,err] = symr(x) %SYMR Rational symbolic representation. [S,err] = mupadmex(' ',x,3); end function S = syme(x) %SYME Symbolic representation with error estimate. if imag(x) > 0 S = ['(' syme(real(x)) ')+(' syme(imag(x)) ')*1i']; elseif imag(x) < 0 S = ['(' syme(real(x)) ')-(' syme(abs(imag(x))) ')*1i']; elseif isinf(x) if x > 0 S = 'Inf'; else S = '-Inf'; end elseif isnan(x) S = 'NaN'; else [S,err] = symr(x); if err ~= 0 err = eval(tofloat(['(' symfl(x) ')-(' S ')'],'32'))/eps; end if err ~= 0 [n,d] = rat(err,1.e-5); if n == 0 || abs(n) > 100000 [n,d] = rat(err/x,1.e-3); if n > 0 S = [S '*(1+' int2str(n) '*eps/' int2str(d) ')']; else S = [S '*(1' int2str(n) '*eps/' int2str(d) ')']; end return end if n == 1 S = [S '+eps']; elseif n == -1 S = [S '-eps']; elseif n > 0 S = [S '+' int2str(n) '*eps']; else S = [S int2str(n) '*eps']; end if d ~= 1 S = [S '/' int2str(d)]; end end end end function S = symd(x,d) %SYMD Decimal symbolic representation. if imag(x) > 0 S = ['(' symd(real(x),d) ')+(' symd(imag(x),d) ')*1i']; elseif imag(x) < 0 S = ['(' symd(real(x),d) ')-(' symd(abs(imag(x)),d) ')*1i']; elseif isinf(x) if x > 0 S = 'Inf'; else S = '-Inf'; end elseif isnan(x) S = 'NaN'; else S = tofloat(symfl(x),int2str(d)); end end function f = symfl(x) %SYMFL Exact representation of floating point number. f = mupadmex(' ',double(x),4); end function B = isNumStr(x) try a = evalin(symengine, ['hold((' x '))']); catch % catch parser errors B = false; return end B = logical(feval(symengine, 'testtype', a, 'Type::Numeric')); if ~B && logical(feval(symengine, 'testtype', a, '"_plus"')) % check whether there exist exactly one complex and one real summand c = children(a); if numel(c) == 2 c1 = feval(symengine, 'op', a, 1); c2 = feval(symengine, 'op', a, 2); B = isComplex(c1) && isReal(c2) || ... isComplex(c2) && isReal(c1); end end end function B = isComplex(x) B = logical(feval(symengine, 'testtype', x, 'DOM_COMPLEX')); end function B = isReal(x) B = logical(feval(symengine, 'testtype', x, 'Type::Union(DOM_INT, DOM_RAT, DOM_FLOAT)')); end function s = convertChar(x) % convertChar(X) converts the string X, including MuPAD array output, to either % a name that is a valid variable name in MuPAD or an expression. % Also checks for MATLAB array syntax for backwards compatibility. % Variable names are checked for overlap with MuPAD names and appends % _Var to the name and returns a reference if the name is used by MuPAD. x = strtrim(x); if any(strcmp(x, constantIdents)) switch(x) case 'catalan' s = 'CATALAN'; case 'eulergamma' s = 'EULER'; case 'pi' s = 'PI'; end elseif isvarname(x) s = convertName(x); elseif isNumStr(x) s = mupadmex({x}); else s = convertExpression(x); end end function s = createCharMatrix(x,a) % Create a symbolic vector or matrix from the variable name x and size vector a. a = double(a); a(a<0) = 0; if any(~isfinite(a)) error(message('symbolic:sym:InvalidSize')); end if any(fix(a)~=a) error(message('symbolic:sym:NonIntegerSize')); end if ~ischar(x) || ~isvarname(strrep(x,'%d','')) error(message('symbolic:sym:SimpleVariable')); end if numel(a) == 1 s = createCharMatrixChecked(x,[a a]); elseif isvector(a) && numel(a) > 1 s = createCharMatrixChecked(x,a); else error(message('symbolic:sym:MatrixArray')); end end function x = appendDefaultFormat(x, missingformats) % Append the default matrix format string if needed if missingformats < 0 error(message('symbolic:sym:FormatTooLong')) elseif missingformats > 0 x = [x '%d' repmat('_%d', [1, missingformats-1])]; % else the number of formats is right and we leave x as it is end end function s = createCharMatrixChecked(x,a) % Create a symbolic matrix from x and size a with total elements n total = prod(a); a = a(:).'; formats = length(find(x == '%')); used = a(a>1); if numel(used) < formats % We use also dimensions equal to 1 if many formats are given used = a; elseif isempty(used) % For sym('x', 1), we create sym('x1') used = 1; end % add some %d if necessary x = appendDefaultFormat(x, numel(used) - formats); % check whether after plugging in the maximal indices, x is a valid % variable name if ~isvarname(sprintf(x, used)) error(message('symbolic:sym:SimpleVariable')); end % special code for 2-dim input if numel(used) == 2 && numel(a) == 2 s = cell(used(1), used(2)); for i=1:used(1) for j=1:used(2) s{i, j} = sprintf(x, i, j); end end else s = cellfun(@(k)createCharMatrixElement(x,used,k),num2cell(1:total),'UniformOutput',false); s = reshape(s,a); end s = mupadmex(s); end function s = createCharMatrixElement(x,a,k) ind = cell(1, numel(a)); [ind{:}] = ind2sub(a,k); s = sprintf(x, ind{:}); end function s = convertName(x) %VARNAME2REF converts a variable name x into a MuPAD name s. % The MuPAD name may have _Var appended to distinguish it from % a predefined MuPAD symbol (like beta or D). s = x; if (length(x)>1 || any(x=='DIOE')) % ask MuPAD to check if the name is defined and internally use a different name xs = mupadmex('symobj::fixupVar',['"' x '"']); s = xs.s; xs.s = ''; end end function s = convertExpression(x) %EXPRESSION2REF converts the string expression x into a string ref s. % The output x is the modified string expression in MuPAD syntax. % Expression input is being deprecated. warning(message('symbolic:sym:sym:DeprecateExpressions')); if isempty(x) x = 'matrix(0,0)'; end if x(1) == '[' x = convertMATLABsyntax(x); end s = mupadmex({x}); end function x = convertMATLABsyntax(x) %convertMATLABsyntax rewrites a MATLAB-style array into a MuPAD array. x = convertSpaces(x); % String contains square brackets, so it is not a scalar. if x(1) == '[' x = convertBrackets(x); end x = ['matrix([' x '])']; end function x = convertSpaces(x) %convertSpaces makes the space-separated array syntax into MuPAD syntax % If the string is of the form, M = '[x - 1 x + 2;x * 3 x / 4]' % then find all of the alpha-numeric chararacters (id), the % arithmetic operators (+ - / * ^) (op), and spaces (sp) and % combine them into a vector V = 3*sp + 2*op + id. That is, % id = isalphanum(M); op = isop(M); sp = find(M == ' '). Let % spaces receive the value 3, operators 2, and alpha-numeric % characters 1. Whenever the sequence 1 3 1 occurs, replace it % with 1 4 1. Insert a comma whenever the number 4 occurs. % First remove all multiple blanks to create at most one blank. sp = (x == ' '); % Location of all the spaces. b = findrun(sp); % Beginning (b) indices. sp(b) = 0; % Mark the beginning of multiple blanks. x(sp) = []; % Set multiple blanks to empty string. V = isalphanum(x) + 2*isop(x) + 3*(x == ' '); if length(V) >= 3 d = V(2:end-1)==3 & V(1:end-2)==1 & V(3:end)==1; V(find(d)+1) = 4; end x(V == 4) = ','; end function x = convertBrackets(x) %convertBrackets makes MATLAB brackets look like MuPAD array. % Make '[a11 a12 ...; a21 a22 ...; ... ]' look like MuPAD array. % Version 1 compatibility. Possibly useful elsewhere. % Replace multiple blanks with single blanks. k = strfind(x,' '); while ~isempty(k); x(k) = []; k = strfind(x,' '); end % Replace blanks surrounded by letters, digits or parens with commas. for k = strfind(x,' '); if (isalphanum(x(k-1)) || x(k-1) == ')') && ... (isalphanum(x(k+1)) || x(k+1) == '(') x(k) = ','; end end % Replace semicolons with '],['. for k = fliplr(strfind(x,';')) x = [x(1:k-1) '],[' x(k+1:end)]; end end function b = findrun(x) %FINDRUN Finds the runs of like elements in a vector. % FINDRUN(V) returns the beginning (b) % indices of the runs of like elements in the vector V. d = diff([0 x 0]); b = find(d == 1); end function B = isalphanum(S) %ISALPHANUM is True for alpha-numeric characters. % ISALPHANUM(S) returns 1 for alpha-numeric characters or % underscores and 0 otherwise. % % Example: S = 'x*exp(x - y) + cosh(x*s^2)' % isalphanum(S) returns % (1,0,1,1,1,0,1,0,0,0,1,0,0,0,0,1,1,1,1,0,1,0,1,0,1,0) B = isletter(S) | (S >= '0' & S <= '9') | (S == '_'); end function B = isop(S) %ISOP is True for + - * / or ^. % ISOP(S) returns 1 for plus, minus, times, divide, or % exponentiation operators and 0 otherwise. B = (S == '+') | (S == '-') | (S == '*') | ... (S == '/') | (S == '^'); end function c = constantIdents %CONSTANTIDENTS Return the mathematical constants c = {'pi', 'eulergamma', 'catalan'}; end function y = tofloat(x,d) %TOFLOAT Convert expression to vpa % Y = TOFLOAT(X,D) converts expression in string X to vpa with digits D. y = mupadmex('symobj::float', x, d, 0); end function s = privformat(x) %PRIVFORMAT Format array into MuPAD indexing string % S = PRIVFORMAT(X) turns X into a string S tailored for calling % MuPAD's indexing code. if isa(x,'sym') x = subsindex(x)+1; end if isscalar(x) s = privformatscalar(x); elseif ismatrix(x) s = privformatmatrix(x); else s = privformatarray(x); end end function s = privformatscalar(x) %PRIVFORMATSCALAR Format scalar object for indexing x = double(x); s = int2str(x); end function s = privformatmatrix(x) %PRIVFORMATMATRIX Format matrix object for indexing d = size(x); s = sprintf('matrix(%d,%d,[',d(1),d(2)); x = double(x); s = [s sprintf('%d,',x.')]; if s(end)==',' s = s(1:end-1); end s = [s '])']; end function s = privformatarray(x) %PRIVFORMATARRAY Format n-d array object for indexing % In MuPAD, the order of the elements is different from MATLAB: % elements only differing in the last index are close together, % while in MATLAB, elements differing only in the first index are. d = size(x); s = ['array(' sprintf('1..%d,',d) '[']; x = permute(double(x), numel(d):-1:1); s = [s sprintf('%d,',x(:))]; if s(end)==',' s = s(1:end-1); end s = [s '])']; end function checkNoSyms(args) if any(cellfun(@(arg)isa(arg,'sym'),args)) error(message('symbolic:ezhelper:TooManySyms')); end end