comparison scripts/polynomial/residue.m @ 1025:f558749713f1

[project @ 1995-01-11 20:52:10 by jwe]
author jwe
date Wed, 11 Jan 1995 20:52:10 +0000
parents 3470f1e25a79
children 611d403c7f3d
comparison
equal deleted inserted replaced
1024:56520a75b5b3 1025:f558749713f1
1 function [r, p, k, e] = residue(b,a,toler) 1 # Copyright (C) 1995 John W. Eaton
2 2 #
3 # [r p k e] = residue(b,a) 3 # This file is part of Octave.
4 #
5 # Octave is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by the
7 # Free Software Foundation; either version 2, or (at your option) any
8 # later version.
9 #
10 # Octave is distributed in the hope that it will be useful, but WITHOUT
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 # for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with Octave; see the file COPYING. If not, write to the Free
17 # Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 function [r, p, k, e] = residue (b, a, toler)
20
21 # usage: [r, p, k, e] = residue (b, a)
22 #
4 # If b and a are vectors of polynomial coefficients, then residue 23 # If b and a are vectors of polynomial coefficients, then residue
5 # calculates the partial fraction expansion corresponding to the 24 # calculates the partial fraction expansion corresponding to the
6 # ratio of the two polynomials. The vector r contains the residue 25 # ratio of the two polynomials. The vector r contains the residue
7 # terms, p contains the pole values, k contains the coefficients of 26 # terms, p contains the pole values, k contains the coefficients of
8 # a direct polynomial term (if it exists) and e is a vector containing 27 # a direct polynomial term (if it exists) and e is a vector containing
15 # 34 #
16 # (# represents summation) where M is the number of poles (the length of 35 # (# represents summation) where M is the number of poles (the length of
17 # the r, p, and e vectors) and N is the length of the k vector. 36 # the r, p, and e vectors) and N is the length of the k vector.
18 # 37 #
19 # [r p k e] = residue(b,a,tol) 38 # [r p k e] = residue(b,a,tol)
39 #
20 # This form of the function call may be used to set a tolerance value. 40 # This form of the function call may be used to set a tolerance value.
21 # The default value is 0.001. The tolerance value is used to determine 41 # The default value is 0.001. The tolerance value is used to determine
22 # whether poles with small imaginary components are declared real. It is 42 # whether poles with small imaginary components are declared real. It is
23 # also used to determine if two poles are distinct. If the ratio of the 43 # also used to determine if two poles are distinct. If the ratio of the
24 # imaginary part of a pole to the real part is less than tol, the imaginary 44 # imaginary part of a pole to the real part is less than tol, the
25 # part is discarded. If two poles are farther apart than tol they are 45 # imaginary part is discarded. If two poles are farther apart than tol
26 # distinct. 46 # they are distinct.
27 # 47 #
28 # Example: 48 # Example:
29 # b = [1 1 1]; 49 # b = [1, 1, 1];
30 # a = [1 -5 8 -4]; 50 # a = [1, -5, 8, -4];
31 # 51 #
32 # [r p k e] = residue(b,a) 52 # [r, p, k, e] = residue (b, a)
33 # 53 #
34 # returns 54 # returns
35 # 55 #
36 # r = [-2 7 3]; p = [2 2 1]; k = []; e = [1 2 1]; 56 # r = [-2, 7, 3]; p = [2, 2, 1]; k = []; e = [1, 2, 1];
37 # 57 #
38 # which implies the following partial fraction expansion 58 # which implies the following partial fraction expansion
39 # 59 #
40 # s^2 + s + 1 -2 7 3 60 # s^2 + s + 1 -2 7 3
41 # ------------------- = ----- + ------- + ----- 61 # ------------------- = ----- + ------- + -----
42 # s^3 - 5s^2 + 8s - 4 (s-2) (s-2)^2 (s-1) 62 # s^3 - 5s^2 + 8s - 4 (s-2) (s-2)^2 (s-1)
43 # 63 #
44 # SEE ALSO: poly, roots, conv, deconv, polyval, polyderiv, polyinteg 64 # SEE ALSO: poly, roots, conv, deconv, polyval, polyderiv, polyinteg
45 65
46 # Author: 66 # Written by Tony Richardson (amr@mpl.ucsd.edu) June 1994.
47 # Tony Richardson
48 # amr@mpl.ucsd.edu
49 # June 1994
50 67
51 # Here's the method used to find the residues. 68 # Here's the method used to find the residues.
52 # The partial fraction expansion can be written as: 69 # The partial fraction expansion can be written as:
53 # 70 #
54 # 71 #
76 # 93 #
77 # or 94 # or
78 # 95 #
79 # s^2 = r(1)*(s^2+2s+1) + r(2)*(s^2+3s+2) +r(3)*(s+2) 96 # s^2 = r(1)*(s^2+2s+1) + r(2)*(s^2+3s+2) +r(3)*(s+2)
80 # 97 #
81 # The coefficients of the polynomials on the right are stored 98 # The coefficients of the polynomials on the right are stored in a row
82 # in a row vector called rhs, while the coefficients of the 99 # vector called rhs, while the coefficients of the polynomial on the
83 # polynomial on the left is stored in a row vector called lhs. 100 # left is stored in a row vector called lhs. If the multiplicity of
84 # If the multiplicity of any root is greater than one we'll 101 # any root is greater than one we'll also need derivatives of this
85 # also need derivatives of this equation of order up to the 102 # equation of order up to the maximum multiplicity minus one. The
86 # maximum multiplicity minus one. The derivative coefficients 103 # derivative coefficients are stored in successive rows of lhs and
87 # are stored in successive rows of lhs and rhs. 104 # rhs.
88 # 105 #
89 # For our example lhs and rhs would be: 106 # For our example lhs and rhs would be:
90 # 107 #
91 # | 1 0 0 | 108 # | 1 0 0 |
92 # lhs = | | 109 # lhs = | |
107 # | 1| = | 0 0 1 | * | r(2) | 124 # | 1| = | 0 0 1 | * | r(2) |
108 # |-2| | 0 1 1 | | r(3) | 125 # |-2| | 0 1 1 | | r(3) |
109 # 126 #
110 # We then solve for the residues using matrix division. 127 # We then solve for the residues using matrix division.
111 128
112 if(nargin < 2 || nargin > 3) 129 if (nargin < 2 || nargin > 3)
113 usage ("residue(b,a[,toler])"); 130 usage ("residue (b, a [, toler])");
114 endif 131 endif
115 132
116 if (nargin == 2) 133 if (nargin == 2)
117 # Set the default tolerance level
118 toler = .001; 134 toler = .001;
119 endif 135 endif
120 136
121 # Make sure both polynomials are in reduced form. 137 # Make sure both polynomials are in reduced form.
122 a = polyreduce(a); 138
123 b = polyreduce(b); 139 a = polyreduce (a);
124 140 b = polyreduce (b);
125 b = b/a(1); 141
126 a = a/a(1); 142 b = b / a(1);
127 143 a = a / a(1);
128 la = length(a); 144
129 lb = length(b); 145 la = length (a);
130 146 lb = length (b);
131 # Handle special cases here. 147
132 if(la == 0 || lb == 0) 148 # Handle special cases here.
149
150 if (la == 0 || lb == 0)
133 k = r = p = e = []; 151 k = r = p = e = [];
134 return; 152 return;
135 elseif (la == 1) 153 elseif (la == 1)
136 k = b/a; 154 k = b / a;
137 r = p = e = []; 155 r = p = e = [];
138 return; 156 return;
139 endif 157 endif
140 158
141 # Find the poles. 159 # Find the poles.
142 p = roots(a); 160
143 lp = length(p); 161 p = roots (a);
144 162 lp = length (p);
145 # Determine if the poles are (effectively) real. 163
146 index = find(abs(imag(p) ./ real(p)) < toler); 164 # Determine if the poles are (effectively) real.
147 if (length(index) != 0) 165
148 p(index) = real(p(index)); 166 index = find (abs (imag (p) ./ real (p)) < toler);
149 endif 167 if (length (index) != 0)
150 168 p (index) = real (p (index));
151 # Find the direct term if there is one. 169 endif
152 if(lb>=la) 170
153 # Also returns the reduced numerator. 171 # Find the direct term if there is one.
154 [k, b] = deconv(b,a); 172
155 lb = length(b); 173 if (lb >= la)
174 # Also returns the reduced numerator.
175 [k, b] = deconv (b, a);
176 lb = length (b);
156 else 177 else
157 k = []; 178 k = [];
158 endif 179 endif
159 180
160 if(lp == 1) 181 if (lp == 1)
161 r = polyval(b,p); 182 r = polyval (b, p);
162 e = 1; 183 e = 1;
163 return; 184 return;
164 endif 185 endif
165 186
166 187
167 # We need to determine the number and multiplicity of the roots. 188 # We need to determine the number and multiplicity of the roots.
168 # D is the number of distinct roots. 189 #
169 # M is a vector of length D containing the multiplicity of each root. 190 # D is the number of distinct roots.
170 # pr is a vector of length D containing only the distinct roots. 191 # M is a vector of length D containing the multiplicity of each root.
171 # e is a vector of length lp which indicates the power in the partial 192 # pr is a vector of length D containing only the distinct roots.
172 # fraction expansion of each term in p. 193 # e is a vector of length lp which indicates the power in the partial
173 194 # fraction expansion of each term in p.
174 # Set initial values. We'll remove elements from pr as we find 195
175 # multiplicities. We'll shorten M afterwards. 196 # Set initial values. We'll remove elements from pr as we find
176 e = ones(lp,1); 197 # multiplicities. We'll shorten M afterwards.
177 M = zeros(lp,1); 198
199 e = ones (lp, 1);
200 M = zeros (lp, 1);
178 pr = p; 201 pr = p;
179 D = 1; M(1) = 1; 202 D = 1;
180 203 M(1) = 1;
181 old_p_index = 1; new_p_index = 2; 204
182 M_index = 1; pr_index = 2; 205 old_p_index = 1;
183 while(new_p_index<=lp) 206 new_p_index = 2;
184 if(abs(p(new_p_index) - p(old_p_index)) < toler) 207 M_index = 1;
185 # We've found a multiple pole. 208 pr_index = 2;
186 M(M_index) = M(M_index) + 1; 209
187 e(new_p_index) = e(new_p_index-1) + 1; 210 while (new_p_index <= lp)
188 # Remove the pole from pr. 211 if (abs (p (new_p_index) - p (old_p_index)) < toler)
189 pr(pr_index) = []; 212 # We've found a multiple pole.
213 M (M_index) = M (M_index) + 1;
214 e (new_p_index) = e (new_p_index-1) + 1;
215 # Remove the pole from pr.
216 pr (pr_index) = [];
190 else 217 else
191 # It's a different pole. 218 # It's a different pole.
192 D++; M_index++; M(M_index) = 1; 219 D++;
193 old_p_index = new_p_index; pr_index++; 220 M_index++;
221 M (M_index) = 1;
222 old_p_index = new_p_index;
223 pr_index++;
194 endif 224 endif
195 new_p_index++; 225 new_p_index++;
196 endwhile 226 endwhile
197 227
198 # Shorten M to it's proper length 228 # Shorten M to it's proper length
199 M = M(1:D); 229
200 230 M = M (1:D);
201 # Now set up the polynomial matrices. 231
232 # Now set up the polynomial matrices.
202 233
203 MM = max(M); 234 MM = max(M);
204 # Left hand side polynomial 235
205 lhs = zeros(MM,lb); 236 # Left hand side polynomial
206 rhs = zeros(MM,lp*lp); 237
207 lhs(1,:) = b; 238 lhs = zeros (MM, lb);
239 rhs = zeros (MM, lp*lp);
240 lhs (1, :) = b;
208 rhi = 1; 241 rhi = 1;
209 dpi = 1; 242 dpi = 1;
210 mpi = 1; 243 mpi = 1;
211 while(dpi<=D) 244 while (dpi <= D)
212 for ind = 1:M(dpi) 245 for ind = 1:M(dpi)
213 if(mpi>1 && (mpi+ind)<=lp) 246 if (mpi > 1 && (mpi+ind) <= lp)
214 cp = [p(1:mpi-1); p(mpi+ind:lp)]; 247 cp = [p(1:mpi-1); p(mpi+ind:lp)];
215 elseif (mpi==1) 248 elseif (mpi == 1)
216 cp = p(mpi+ind:lp); 249 cp = p (mpi+ind:lp);
217 else 250 else
218 cp = p(1:mpi-1); 251 cp = p (1:mpi-1);
219 endif 252 endif
220 rhs(1,rhi:rhi+lp-1) = prepad(poly(cp),lp); 253 rhs (1, rhi:rhi+lp-1) = prepad (poly (cp), lp);
221 rhi = rhi + lp; 254 rhi = rhi + lp;
222 endfor 255 endfor
223 mpi = mpi + M(dpi); 256 mpi = mpi + M (dpi);
224 dpi++; 257 dpi++;
225 endwhile 258 endwhile
226 if(MM > 1) 259 if (MM > 1)
227 for index = 2:MM 260 for index = 2:MM
228 lhs(index,:) = prepad(polyderiv(lhs(index-1,:)),lb); 261 lhs (index, :) = prepad (polyderiv (lhs (index-1, :)), lb);
229 ind = 1; 262 ind = 1;
230 for rhi = 1:lp 263 for rhi = 1:lp
231 cp = rhs(index-1,ind:ind+lp-1); 264 cp = rhs (index-1, ind:ind+lp-1);
232 rhs(index,ind:ind+lp-1) = prepad(polyderiv(cp),lp); 265 rhs (index, ind:ind+lp-1) = prepad (polyderiv (cp), lp);
233 ind = ind + lp; 266 ind = ind + lp;
234 endfor 267 endfor
235 endfor 268 endfor
236 endif 269 endif
237 270
238 # Now lhs contains the numerator polynomial and as many derivatives as are 271 # Now lhs contains the numerator polynomial and as many derivatives as
239 # required. rhs is a matrix of polynomials, the first row contains the 272 # are required. rhs is a matrix of polynomials, the first row
240 # corresponding polynomial for each residue and successive rows are 273 # contains the corresponding polynomial for each residue and
241 # derivatives. 274 # successive rows are derivatives.
242 275
243 # Now we need to evaluate the first row of lhs and rhs at each distinct 276 # Now we need to evaluate the first row of lhs and rhs at each
244 # pole value. If there are multiple poles we will also need to evaluate 277 # distinct pole value. If there are multiple poles we will also need
245 # the derivatives at the pole value also. 278 # to evaluate the derivatives at the pole value also.
246 279
247 B = zeros(lp,1); 280 B = zeros (lp, 1);
248 A = zeros(lp,lp); 281 A = zeros (lp, lp);
249 282
250 dpi = 1; 283 dpi = 1;
251 row = 1; 284 row = 1;
252 while(dpi<=D) 285 while (dpi <= D)
253 for mi = 1:M(dpi) 286 for mi = 1:M(dpi)
254 B(row) = polyval(lhs(mi,:),pr(dpi)); 287 B (row) = polyval (lhs (mi, :), pr (dpi));
255 ci = 1; 288 ci = 1;
256 for col = 1:lp 289 for col = 1:lp
257 cp = rhs(mi,ci:ci+lp-1); 290 cp = rhs (mi, ci:ci+lp-1);
258 A(row,col) = polyval(cp,pr(dpi)); 291 A (row, col) = polyval (cp, pr(dpi));
259 ci = ci + lp; 292 ci = ci + lp;
260 endfor 293 endfor
261 row++; 294 row++;
262 endfor 295 endfor
263 dpi++; 296 dpi++;
264 endwhile 297 endwhile
265 298
266 # Solve for the residues. 299 # Solve for the residues.
267 r = A\B; 300
301 r = A \ B;
268 302
269 endfunction 303 endfunction