⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mldivide.m

📁 几个关于多小波的程序
💻 M
字号:
function [Q,method] = mldivide(P1,P2)

% MLDIVIDE -- left division of matrix polynomials
%
%        Q = P1 \ P2
%        Q = mldivide(P1,P2)
%
% This function is not meant to be called by the user. It is called by
% Matlab if an expression of the form P1\P2 is encountered, where at
% least one of the two operands is a matrix polynomial. P1 must be
% square, either of a size compatible with P2 or a scalar.
%
% This routine knows how to handle 3 special cases at the moment,
% otherwise it gives up:
%
% 1. P1 has a nonsingular first or last coefficient, in which case
%    we can do long division; if it fails, we know that division is
%    not possible. The cases P1 = monomial and P1 = scalar fall into
%    this category
%
% 2. P1 is a projection factor, which has a known inverse
%
% 3. P1 is upper or lower triangular, with an invertible diagonal; this
%    includes the case P1 = diagonal matrix.
%
% If none of these cases apply, division may or may not be possible.
% As a last resort, you could try Q = longinv(P1) * P2.
%
% For symbolic matrices, this routine may take a long time and
% return a very complicated result.
%
% The METHOD output parameter is strictly for testing purposes. It 
% indicates which of the special cases was applied.

% Copyright (c) 2004 by Fritz Keinert (keinert@iastate.edu),
% Dept. of Mathematics, Iowa State University, Ames, IA 50011.
% This software may be freely used and distributed for non-commercial
% purposes, provided this copyright statement is preserved, and
% appropriate credit for its use is given.
%
% Last update: Feb 20, 2004

% make sure P1, P2 are both matrix polynomials

if ~isa(P1,'mpoly')
    P1 = mpoly(P1);
end
if ~isa(P2,'mpoly')
    P2 = mpoly(P2);
end
P1 = trim(P1);
P2 = trim(P2);
P2max = get(P2,'max');

% check that P1 is square and compatible with P2

[n1,n2] = size(P1);
[m1,m2] = size(P2);
if (n1 ~= n2 | (n1 ~= 1 & n1 ~= m1))
    error('incompatible sizes in division');
end

% Case 1: check if either the first or last coefficient of P1 is
% non-singular. If yes, attempt long division. 
%
% If the first coefficient is nonsingular, we divide left to right. 
% If the last coefficient is nonsingular, but not the first, we would
% have to do the division right to left. To save on programming
% effort, I instead reverse the order of the coefficients before and
% after the division.
%
% If both the first and last coefficients of P1 are nonsingular 
% (which includes the cases P1 = scalar and P1 = monomial), then 
% degree of Q = degree of P2 - degree of P1. 
%
% Otherwise, the degree of Q could be larger. The worst case I can
% think of that could be useful is when P1 is unit lower or upper
% triangular, in which case the degree of P1inv could be as large as
% (n-1)*(degree of P1), n = size of P1. If the division does not
% terminate at that point, we give up.

% Algorithm:
%
% 1. Pad P2 with P2extra zero matrices, where P2extra=0 if the first
% and last coefficient of P1 are both non-singular, and 
% P2extra=n*(length(P1)-1) otherwise. 
%
% The earliest possibility for the division to terminate
% successfully is when we reach the end of the original P2, which is
% after 
%
%        kmin = length(P2) - length(P1) + 1
%
% division steps. The last possibility we consider is when we reach
% the end of (P2 + P2extra zeros), which happens after
%
%        kmax = kmin + P2extra
%
% steps.
%
% We start with (kmin-1) division steps without checking the
% remainder, then we start checking.

method = 1;

first = ~issingular(P1.coef(:,:,1));
last  = ~issingular(P1.coef(:,:,end));

if (last & ~first)
    P1 = reverse(P1);
    P2 = reverse(P2);
end
    
if (~first & size(P1.coef,3) == 1)
% we are trying to divide by a single singular matrix
    error('left division failed');
end

if (first | last)
    P1length = size(P1.coef,3);
    P2length = size(P2.coef,3);
    if (first & last)
	if (P2length < P1length)
	    error('left division failed');
	end
	P2extra = 0;
    else
	P2extra = n1 * (P1length - 1);
    end
    Qlengthmin = P2length - P1length + 1;
    Qlength = Qlengthmin + P2extra;
    % pad P2 with P2extra zeros
    P2 = trim(P2,[P2.min,P2max+P2extra]);
    % do division
    for i = 1:Qlength
	Qcoef(:,:,i) = P1.coef(:,:,1) \ P2.coef(:,:,i);
	for j = 2:P1length
	    P2.coef(:,:,i+j-1) = P2.coef(:,:,i+j-1) - P1.coef(:,:,j)*Qcoef(:,:,i);
	end
	if (i >= Qlengthmin) % check remainder
	    remainder = mpoly(P2.coef(:,:,i+1:i+P1length-1));
	    if iszero(remainder) % success!
		Q = mpoly(Qcoef,P2.min-P1.min);
		Q = trim(Q);
		if (last & ~first)
		    Q = reverse(Q);
		end
		[type,m,r] = match_type(P1,P2);
		Q = set(Q,'type',type,'m',m,'r',r);
		return
	    end
	end
    end
% If we get to this point, long division failed.
% If the first and last coefficients do not contain symbolic variables,
% we know that division is not possible
    if (~issymbolic(P1.coef(:,:,1)) & ~issymbolic(P1.coef(:,:,end)))
	error('left division failed');
    end
end


% case 2: check if P1 is a generalized projection factor
% That means we try to factor P1 as
%
%                              s   k
%        P1 = P1  [ A + (I-A) z ] z
%               0
%       2
% with A  = A. If this succeeds, then
%
%          -1               -s    -1  -k
%        P1   = [A + (I-A) z  ] P1   z
%                                 0

method = 2;

P10 = moment(P1);
if ~issingular(P10)
    F = P1;
    for i = 1:size(F.coef,3)
	F.coef(:,:,i) = P10 \ F.coef(:,:,i);
    end
    A = F.coef(:,:,1);
    if iszero(A^2 - A)
	if iszero(F.coef(:,:,end) - eye(n1) + A)
	    k = F.min;
	    s = F.min + size(F.coef,3) - 1 - k;
	    middle = mpoly(F.coef(:,:,2:end-1));
	    if iszero(middle) % success!
		P1inv = F;
		P1inv.coef(:,:,1) = eye(n1) - A;
		P1inv.coef(:,:,end) = A;
		P1inv.min = - k - s;
		for i = 1:size(P1inv.coef,3)
		    P1inv.coef(:,:,i) = P1inv.coef(:,:,i) / P10;
		end
		Q = trim(P1inv * P2);
		[type,m,r] = match_type(P1,P2);
		Q = set(Q,'type',type,'m',m,'r',r);
		return
	    end
	end
    end
end

% case 3: check if the matrix is upper or lower triangular
% If it is, we attempt forward or back substitution.

method = 3;

if iszero(triu(P1,1)) % matrix is lower triangular
    Q = mpoly(zeros(m1,m2),0);
    if (isa(P1.coef,'sym') | isa(P2.coef,'sym'))
	Q = sym(Q);
    end
% Q(1,:) = P1(1,1) \ P2(1,:);
    Q = subsasgn(Q,substruct('()',{1,':'}),...
		 subsref(P1,substruct('()',{1,1})) \ ...
		 subsref(P2,substruct('()',{1,':'}))); 
    for j = 2:m1
% Q(j,:) = P1(j,j) \ (P2(j,:) - P1(j,1:j-1)*Q(1:j-1,:));
	Q = subsasgn(Q,substruct('()',{j,':'}),...
		     subsref(P1,substruct('()',{j,j})) \ ...
		     (subsref(P2,substruct('()',{j,':'})) - ...
		      subsref(P1,substruct('()',{j,1:j-1})) * ...
		      subsref(Q,substruct('()',{1:j-1,':'}))));
    end
    Q = trim(Q);
    [type,m,r] = match_type(P1,P2);
    Q = set(Q,'type',type,'m',m,'r',r);
    return
elseif iszero(tril(P1,-1)) % matrix is upper triangular
    Q = mpoly(zeros(m1,m2),0);
    % Q(m1,:) = P1(m1,m1) \ P2(m1,:);
    Q = subsasgn(Q,substruct('()',{m1,':'}),...
	subsref(P1,substruct('()',{m1,m1})) \ ...
	subsref(P2,substruct('()',{m1,':'}))); 
    for j = m1-1:-1:1
	% Q(j,:) = P1(j,j) \ (P2(j,:) - P1(j,j+1:m1)*Q(j+1:m1,:));
	Q = subsasgn(Q,substruct('()',{j,':'}),...
	    subsref(P1,substruct('()',{j,j})) \ ...
	    (subsref(P2,substruct('()',{j,':'})) - ...
	    subsref(P1,substruct('()',{j,j+1:m1})) * ...
	    subsref(Q,substruct('()',{j+1:m1,':'}))));
    end
    Q = trim(Q);
    [type,m,r] = match_type(P1,P2);
    Q = set(Q,'type',type,'m',m,'r',r);
    return
end

% if we get to this point, division has failed

error('left division failed');

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -