Mercurial > hg > octave-nkf
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 |