Mercurial > hg > octave-lyh
comparison scripts/polynomial/residue.m @ 6964:33f20a41aeea
[project @ 2007-10-06 04:31:18 by jwe]
author | jwe |
---|---|
date | Sat, 06 Oct 2007 04:31:18 +0000 |
parents | 34f96dd5441b |
children | c8fc3487ed2c |
comparison
equal
deleted
inserted
replaced
6963:642f481d2d50 | 6964:33f20a41aeea |
---|---|
1 ## Copyright (C) 1996, 1997 John W. Eaton | 1 ## Copyright (C) 1996, 1997 John W. Eaton |
2 ## Copyright (C) 2007 Ben Abbott | |
2 ## | 3 ## |
3 ## This file is part of Octave. | 4 ## This file is part of Octave. |
4 ## | 5 ## |
5 ## Octave is free software; you can redistribute it and/or modify it | 6 ## 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 | 7 ## under the terms of the GNU General Public License as published by |
16 ## along with Octave; see the file COPYING. If not, write to the Free | 17 ## along with Octave; see the file COPYING. If not, write to the Free |
17 ## Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | 18 ## Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
18 ## 02110-1301, USA. | 19 ## 02110-1301, USA. |
19 | 20 |
20 ## -*- texinfo -*- | 21 ## -*- texinfo -*- |
21 ## @deftypefn {Function File} {} residue (@var{b}, @var{a}, @var{tol}) | 22 ## @deftypefn {Function File} {[@var{r}, @var{p}, @var{k}] =} residue (@var{b}, @var{a}) |
22 ## If @var{b} and @var{a} are vectors of polynomial coefficients, then | 23 ## @deftypefnx {Function File} {[@var{b}, @var{a}] =} residue (@var{r}, @var{p}, @var{k}) |
23 ## residue calculates the partial fraction expansion corresponding to the | 24 ## In the instance of two inputs, they are assumed to correspond to vectors |
24 ## ratio of the two polynomials. | 25 ## of polynomial coefficients, @var{b} and @var{a}. From these polynomial |
26 ## coefficients, the function residue calculates the partial fraction | |
27 ## expansion corresponding to the ratio of the two polynomials. | |
25 ## @cindex partial fraction expansion | 28 ## @cindex partial fraction expansion |
26 ## | 29 ## |
27 ## The function @code{residue} returns @var{r}, @var{p}, @var{k}, and | 30 ## In this instance, the function @code{residue} returns @var{r}, @var{p}, |
28 ## @var{e}, where the vector @var{r} contains the residue terms, @var{p} | 31 ## and @var{k}, where the vector @var{r} contains the residue terms, |
29 ## contains the pole values, @var{k} contains the coefficients of a direct | 32 ## @var{p} contains the pole values, @var{k} contains the coefficients of a |
30 ## polynomial term (if it exists) and @var{e} is a vector containing the | 33 ## direct polynomial term (if it exists). |
31 ## powers of the denominators in the partial fraction terms. | 34 ## |
35 ## In the instance of three inputs, the function 'residue' performs the | |
36 ## reciprocal task. Meaning the partial fraction expansion is reconstituted | |
37 ## into the corresponding pair of polynomial coefficients. | |
32 ## | 38 ## |
33 ## Assuming @var{b} and @var{a} represent polynomials | 39 ## Assuming @var{b} and @var{a} represent polynomials |
34 ## @iftex | 40 ## @iftex |
35 ## @tex | 41 ## @tex |
36 ## $P(s)$ and $Q(s)$ | 42 ## $P(s)$ and $Q(s)$ |
58 ## @end ifinfo | 64 ## @end ifinfo |
59 ## | 65 ## |
60 ## @noindent | 66 ## @noindent |
61 ## where @math{M} is the number of poles (the length of the @var{r}, | 67 ## where @math{M} is the number of poles (the length of the @var{r}, |
62 ## @var{p}, and @var{e} vectors) and @math{N} is the length of the | 68 ## @var{p}, and @var{e} vectors) and @math{N} is the length of the |
63 ## @var{k} vector. | 69 ## @var{k} vector. The @var{e} vector specifies the multiplicity of the |
64 ## | 70 ## mth residue's pole. |
65 ## The argument @var{tol} is optional, and if not specified, a default | 71 ## |
66 ## value of 0.001 is assumed. The tolerance value is used to determine | 72 ## For example, |
67 ## whether poles with small imaginary components are declared real. It is | |
68 ## also used to determine if two poles are distinct. If the ratio of the | |
69 ## imaginary part of a pole to the real part is less than @var{tol}, the | |
70 ## imaginary part is discarded. If two poles are farther apart than | |
71 ## @var{tol} they are distinct. For example, | |
72 ## | 73 ## |
73 ## @example | 74 ## @example |
74 ## @group | 75 ## @group |
75 ## b = [1, 1, 1]; | 76 ## b = [1, 1, 1]; |
76 ## a = [1, -5, 8, -4]; | 77 ## a = [1, -5, 8, -4]; |
77 ## [r, p, k, e] = residue (b, a); | 78 ## [r, p, k] = residue (b, a); |
78 ## @result{} r = [-2, 7, 3] | 79 ## @result{} r = [-2, 7, 3] |
79 ## @result{} p = [2, 2, 1] | 80 ## @result{} p = [2, 2, 1] |
80 ## @result{} k = [](0x0) | 81 ## @result{} k = [](0x0) |
81 ## @result{} e = [1, 2, 1] | |
82 ## @end group | 82 ## @end group |
83 ## @end example | 83 ## @end example |
84 ## | 84 ## |
85 ## @noindent | 85 ## @noindent |
86 ## which implies the following partial fraction expansion | 86 ## which implies the following partial fraction expansion |
96 ## @example | 96 ## @example |
97 ## s^2 + s + 1 -2 7 3 | 97 ## s^2 + s + 1 -2 7 3 |
98 ## ------------------- = ----- + ------- + ----- | 98 ## ------------------- = ----- + ------- + ----- |
99 ## s^3 - 5s^2 + 8s - 4 (s-2) (s-2)^2 (s-1) | 99 ## s^3 - 5s^2 + 8s - 4 (s-2) (s-2)^2 (s-1) |
100 ## @end example | 100 ## @end example |
101 ## | |
101 ## @end ifinfo | 102 ## @end ifinfo |
102 ## @seealso{poly, roots, conv, deconv, polyval, polyderiv, and polyinteg} | 103 ## A similar, but reciprocal example, where the fraction's polynomials are |
104 ## reconstituted from the residues, poles, and direct term is | |
105 ## | |
106 ## @example | |
107 ## @group | |
108 ## r = [-2, 7, 3]; | |
109 ## p = [2, 2, 1]; | |
110 ## k = [1 0]; | |
111 ## [b, a] = residue (r, p, k); | |
112 ## @result{} b = [1, -5, 9, -3, 1] | |
113 ## @result{} a = [1, -5, 8, 4] | |
114 ## @end group | |
115 ## @end example | |
116 ## | |
117 ## @noindent | |
118 ## which implies the following partial fraction expansion | |
119 ## @iftex | |
120 ## @tex | |
121 ## $$ | |
122 ## {s^4-5s^3+9s^2-3s+1\over s^3-5s^2+8s-4} = {-2\over s-2} + {7\over (s-2)^2} + {3\over s-1} + s | |
123 ## $$ | |
124 ## @end tex | |
125 ## @end iftex | |
126 ## @ifinfo | |
127 ## | |
128 ## @example | |
129 ## s^4 - 5s^3 + 9s^2 - 3s + 1 -2 7 3 | |
130 ## -------------------------- = ----- + ------- + ----- + s | |
131 ## s^3 - 5s^2 + 8s - 4 (s-2) (s-2)^2 (s-1) | |
132 ## @end example | |
133 ## @end ifinfo | |
134 ## @seealso{poly, roots, conv, deconv, mpoles, polyval, polyderiv, polyinteg} | |
103 ## @end deftypefn | 135 ## @end deftypefn |
104 | 136 |
105 ## Author: Tony Richardson <arichard@stark.cc.oh.us> | 137 ## Author: Tony Richardson <arichard@stark.cc.oh.us> |
138 ## Author: Ben Abbott <bpabbott@mac.com> | |
106 ## Created: June 1994 | 139 ## Created: June 1994 |
107 ## Adapted-By: jwe | 140 ## Adapted-By: jwe |
108 | 141 |
109 function [r, p, k, e] = residue (b, a, toler) | 142 function [r, p, k] = residue (b, a, varargin) |
110 | |
111 ## Here's the method used to find the residues. | |
112 ## The partial fraction expansion can be written as: | |
113 ## | |
114 ## | |
115 ## P(s) D M(k) A(k,m) | |
116 ## ---- = # # ------------- | |
117 ## Q(s) k=1 m=1 (s - pr(k))^m | |
118 ## | |
119 ## (# is used to represent a summation) where D is the number of | |
120 ## distinct roots, pr(k) is the kth distinct root, M(k) is the | |
121 ## multiplicity of the root, and A(k,m) is the residue cooresponding | |
122 ## to the kth distinct root with multiplicity m. For example, | |
123 ## | |
124 ## s^2 A(1,1) A(2,1) A(2,2) | |
125 ## ------------------- = ------ + ------ + ------- | |
126 ## s^3 + 4s^2 + 5s + 2 (s+2) (s+1) (s+1)^2 | |
127 ## | |
128 ## In this case there are two distinct roots (D=2 and pr = [-2 -1]), | |
129 ## the first root has multiplicity one and the second multiplicity | |
130 ## two (M = [1 2]) The residues are actually stored in vector format as | |
131 ## r = [ A(1,1) A(2,1) A(2,2) ]. | |
132 ## | |
133 ## We then multiply both sides by Q(s). Continuing the example: | |
134 ## | |
135 ## s^2 = r(1)*(s+1)^2 + r(2)*(s+1)*(s+2) + r(3)*(s+2) | |
136 ## | |
137 ## or | |
138 ## | |
139 ## s^2 = r(1)*(s^2+2s+1) + r(2)*(s^2+3s+2) +r(3)*(s+2) | |
140 ## | |
141 ## The coefficients of the polynomials on the right are stored in a row | |
142 ## vector called rhs, while the coefficients of the polynomial on the | |
143 ## left is stored in a row vector called lhs. If the multiplicity of | |
144 ## any root is greater than one we'll also need derivatives of this | |
145 ## equation of order up to the maximum multiplicity minus one. The | |
146 ## derivative coefficients are stored in successive rows of lhs and | |
147 ## rhs. | |
148 ## | |
149 ## For our example lhs and rhs would be: | |
150 ## | |
151 ## | 1 0 0 | | |
152 ## lhs = | | | |
153 ## | 0 2 0 | | |
154 ## | |
155 ## | 1 2 1 1 3 2 0 1 2 | | |
156 ## rhs = | | | |
157 ## | 0 2 2 0 2 3 0 0 1 | | |
158 ## | |
159 ## We then form a vector B and a matrix A obtained by evaluating the | |
160 ## polynomials in lhs and rhs at the pole values. If a pole has a | |
161 ## multiplicity greater than one we also evaluate the derivative | |
162 ## polynomials (successive rows) at the pole value. | |
163 ## | |
164 ## For our example we would have | |
165 ## | |
166 ## | 4| | 1 0 0 | | r(1) | | |
167 ## | 1| = | 0 0 1 | * | r(2) | | |
168 ## |-2| | 0 1 1 | | r(3) | | |
169 ## | |
170 ## We then solve for the residues using matrix division. | |
171 | 143 |
172 if (nargin < 2 || nargin > 3) | 144 if (nargin < 2 || nargin > 3) |
173 print_usage (); | 145 print_usage (); |
174 endif | 146 endif |
175 | 147 |
176 if (nargin == 2) | 148 toler = .001; |
177 toler = .001; | 149 |
178 endif | 150 if (nargin == 3) |
151 ## The inputs are the residue, pole, and direct part. Solve for the | |
152 ## corresponding numerator and denominator polynomials | |
153 [r, p] = rresidue (b, a, varargin{1}, toler); | |
154 return | |
155 end | |
179 | 156 |
180 ## Make sure both polynomials are in reduced form. | 157 ## Make sure both polynomials are in reduced form. |
181 | 158 |
182 a = polyreduce (a); | 159 a = polyreduce (a); |
183 b = polyreduce (b); | 160 b = polyreduce (b); |
204 p = roots (a); | 181 p = roots (a); |
205 lp = length (p); | 182 lp = length (p); |
206 | 183 |
207 ## Determine if the poles are (effectively) zero. | 184 ## Determine if the poles are (effectively) zero. |
208 | 185 |
209 p(abs (p) < toler) = 0; | 186 small = max (abs (p)); |
210 | 187 small = max ([small, 1] ) * 1e-8 * (1 + numel (p))^2; |
211 ## Determine if the poles are (effectively) real. | 188 p(abs (p) < small) = 0; |
212 | 189 |
213 index = (abs (p) >= toler & (abs (imag (p)) ./ abs (p) < toler)); | 190 ## Determine if the poles are (effectively) real, or imaginary. |
191 | |
192 index = (abs (imag (p)) < small); | |
214 p(index) = real (p(index)); | 193 p(index) = real (p(index)); |
194 index = (abs (real (p)) < small); | |
195 p(index) = 1i * imag (p(index)); | |
196 | |
197 ## Sort poles so that multiplicity loop will work. | |
198 | |
199 [e, indx] = mpoles (p, toler, 1); | |
200 p = p (indx); | |
215 | 201 |
216 ## Find the direct term if there is one. | 202 ## Find the direct term if there is one. |
217 | 203 |
218 if (lb >= la) | 204 if (lb >= la) |
219 ## Also returns the reduced numerator. | 205 ## Also return the reduced numerator. |
220 [k, b] = deconv (b, a); | 206 [k, b] = deconv (b, a); |
221 lb = length (b); | 207 lb = length (b); |
222 else | 208 else |
223 k = []; | 209 k = []; |
224 endif | 210 endif |
225 | 211 |
226 if (lp == 1) | 212 if (lp == 1) |
227 r = polyval (b, p); | 213 r = polyval (b, p); |
228 e = 1; | |
229 return; | 214 return; |
230 endif | 215 endif |
231 | 216 |
232 ## We need to determine the number and multiplicity of the roots. | 217 ## Determine the order of the denominator and remaining numerator. |
233 ## | 218 ## With the direct term removed the potential order of the numerator |
234 ## D is the number of distinct roots. | 219 ## is one less than the order of the denominator. |
235 ## M is a vector of length D containing the multiplicity of each root. | 220 |
236 ## pr is a vector of length D containing only the distinct roots. | 221 aorder = numel (a) - 1; |
237 ## e is a vector of length lp which indicates the power in the partial | 222 border = aorder - 1; |
238 ## fraction expansion of each term in p. | 223 |
239 | 224 ## Construct a system of equations relating the individual |
240 ## Set initial values. We'll remove elements from pr as we find | 225 ## contributions from each residue to the complete numerator. |
241 ## multiplicities. We'll shorten M afterwards. | 226 |
242 | 227 A = zeros (border+1, border+1); |
243 e = ones (lp, 1); | 228 B = prepad (reshape (b, [numel(b), 1]), border+1, 0); |
244 M = zeros (lp, 1); | 229 for ip = 1:numel(p) |
245 pr = p; | 230 ri = zeros (size (p)); |
246 D = 1; | 231 ri(ip) = 1; |
247 M(1) = 1; | 232 A(:,ip) = prepad (rresidue (ri, p, [], toler), border+1, 0).'; |
248 | 233 endfor |
249 old_p_index = 1; | 234 |
250 new_p_index = 2; | 235 ## Solve for the residues. |
251 M_index = 1; | 236 |
252 pr_index = 2; | 237 r = A \ B; |
253 | 238 |
254 while (new_p_index <= lp) | 239 endfunction |
255 if (abs (p (new_p_index) - p (old_p_index)) < toler) | 240 |
256 ## We've found a multiple pole. | 241 function [pnum, pden] = rresidue (r, p, k, toler) |
257 M (M_index) = M (M_index) + 1; | 242 |
258 e (new_p_index) = e (new_p_index-1) + 1; | 243 ## Reconstitute the numerator and denominator polynomials from the |
259 ## Remove the pole from pr. | 244 ## residues, poles, and direct term. |
260 pr (pr_index) = []; | 245 |
246 if (nargin < 2 || nargin > 4) | |
247 print_usage (); | |
248 endif | |
249 | |
250 if (nargin < 4) | |
251 toler = []; | |
252 endif | |
253 | |
254 if (nargin < 3) | |
255 k = []; | |
256 endif | |
257 | |
258 [multp, indx] = mpoles (p, toler, 0); | |
259 | |
260 p = p (indx); | |
261 r = r (indx); | |
262 | |
263 indx = 1:numel(p); | |
264 | |
265 for n = indx | |
266 pn = [1, -p(n)]; | |
267 if n == 1 | |
268 pden = pn; | |
261 else | 269 else |
262 ## It's a different pole. | 270 pden = conv (pden, pn); |
263 D++; | |
264 M_index++; | |
265 M (M_index) = 1; | |
266 old_p_index = new_p_index; | |
267 pr_index++; | |
268 endif | 271 endif |
269 new_p_index++; | 272 endfor |
270 endwhile | 273 |
271 | 274 ## D is the order of the denominator |
272 ## Shorten M to it's proper length | 275 ## K is the order of the direct polynomial |
273 | 276 ## N is the order of the resulting numerator |
274 M = M (1:D); | 277 ## pnum(1:(N+1)) is the numerator's polynomial |
275 | 278 ## pden(1:(D+1)) is the denominator's polynomial |
276 ## Now set up the polynomial matrices. | 279 ## pm is the multible pole for the nth residue |
277 | 280 ## pn is the numerator contribution for the nth residue |
278 MM = max(M); | 281 |
279 | 282 D = numel (pden) - 1; |
280 ## Left hand side polynomial | 283 K = numel (k) - 1; |
281 | 284 N = K + D; |
282 lhs = zeros (MM, lb); | 285 pnum = zeros (1, N+1); |
283 rhs = zeros (MM, lp*lp); | 286 for n = indx(abs(r)>0) |
284 lhs (1, :) = b; | 287 p1 = [1, -p(n)]; |
285 rhi = 1; | 288 for m = 1:multp(n) |
286 dpi = 1; | 289 if m == 1 |
287 mpi = 1; | 290 pm = p1; |
288 while (dpi <= D) | |
289 for ind = 1:M(dpi) | |
290 if (mpi > 1 && (mpi+ind) <= lp) | |
291 cp = [p(1:mpi-1); p(mpi+ind:lp)]; | |
292 elseif (mpi == 1) | |
293 cp = p (mpi+ind:lp); | |
294 else | 291 else |
295 cp = p (1:mpi-1); | 292 pm = conv (pm, p1); |
296 endif | 293 endif |
297 rhs (1, rhi:rhi+lp-1) = prepad (poly (cp), lp, 0, 2); | |
298 rhi = rhi + lp; | |
299 endfor | 294 endfor |
300 mpi = mpi + M (dpi); | 295 pn = deconv (pden, pm); |
301 dpi++; | 296 pn = r(n) * pn; |
302 endwhile | 297 pnum = pnum + prepad ( pn, N+1, 0); |
303 if (MM > 1) | 298 endfor |
304 for index = 2:MM | 299 |
305 lhs (index, :) = prepad (polyderiv (lhs (index-1, :)), lb, 0, 2); | 300 ## Add the direct term. |
306 ind = 1; | 301 |
307 for rhi = 1:lp | 302 if (numel (k)) |
308 cp = rhs (index-1, ind:ind+lp-1); | 303 pnum = pnum + conv (pden, k); |
309 rhs (index, ind:ind+lp-1) = prepad (polyderiv (cp), lp, 0, 2); | 304 endif |
310 ind = ind + lp; | 305 |
311 endfor | 306 ## Check for leading zeros and trim the polynomial coefficients. |
312 endfor | 307 |
313 endif | 308 small = max ([max(abs(pden)), max(abs(pnum)), 1]) * eps; |
314 | 309 |
315 ## Now lhs contains the numerator polynomial and as many derivatives as | 310 pnum (abs (pnum) < small) = 0; |
316 ## are required. rhs is a matrix of polynomials, the first row | 311 pden (abs (pden) < small) = 0; |
317 ## contains the corresponding polynomial for each residue and | 312 |
318 ## successive rows are derivatives. | 313 pnum = polyreduce (pnum); |
319 | 314 pden = polyreduce (pden); |
320 ## Now we need to evaluate the first row of lhs and rhs at each | |
321 ## distinct pole value. If there are multiple poles we will also need | |
322 ## to evaluate the derivatives at the pole value also. | |
323 | |
324 B = zeros (lp, 1); | |
325 A = zeros (lp, lp); | |
326 | |
327 dpi = 1; | |
328 row = 1; | |
329 while (dpi <= D) | |
330 for mi = 1:M(dpi) | |
331 B (row) = polyval (lhs (mi, :), pr (dpi)); | |
332 ci = 1; | |
333 for col = 1:lp | |
334 cp = rhs (mi, ci:ci+lp-1); | |
335 A (row, col) = polyval (cp, pr(dpi)); | |
336 ci = ci + lp; | |
337 endfor | |
338 row++; | |
339 endfor | |
340 dpi++; | |
341 endwhile | |
342 | |
343 ## Solve for the residues. | |
344 | |
345 r = A \ B; | |
346 | 315 |
347 endfunction | 316 endfunction |