comparison src/DLD-FUNCTIONS/qz.cc @ 3185:9580887dd160

[project @ 1998-09-26 02:45:55 by jwe]
author jwe
date Sat, 26 Sep 1998 02:45:59 +0000
parents 5edc539c2f80
children 3d3eca53ecca
comparison
equal deleted inserted replaced
3184:3988763ec9d3 3185:9580887dd160
45 #include "help.h" 45 #include "help.h"
46 #include "oct-obj.h" 46 #include "oct-obj.h"
47 #include "oct-map.h" 47 #include "oct-map.h"
48 #include "ov.h" 48 #include "ov.h"
49 #include "pager.h" 49 #include "pager.h"
50 #if defined(DEBUG) || defined(DEBUG_SORT) 50 #if defined (DEBUG) || defined (DEBUG_SORT)
51 #include "pr-output.h" 51 #include "pr-output.h"
52 #endif 52 #endif
53 #include "symtab.h" 53 #include "symtab.h"
54 #include "utils.h" 54 #include "utils.h"
55 #include "variables.h" 55 #include "variables.h"
56 56
57 typedef int (*sort_function) (const int& LSIZE, const double& ALPHA, 57 typedef int (*sort_function) (const int& LSIZE, const double& ALPHA,
58 const double& BETA, const double& S, const double& P); 58 const double& BETA, const double& S,
59 const double& P);
59 60
60 extern "C" 61 extern "C"
61 { 62 {
62 int F77_FCN( dggbal, DGGBAL) (const char* JOB, const int& N, 63 int F77_FCN (dggbal, DGGBAL) (const char* JOB, const int& N,
63 double* A, const int& LDA, double* B, const int& LDB, 64 double* A, const int& LDA, double* B,
64 int& ILO, int & IHI, double* LSCALE, 65 const int& LDB, int& ILO, int& IHI,
65 double* RSCALE, double* WORK, int& INFO, long ); 66 double* LSCALE, double* RSCALE,
66 67 double* WORK, int& INFO, long);
67 int F77_FCN( dggbak, DGGBAK) (const char* JOB, const char* SIDE, 68
68 const int& N, const int& ILO, const int& IHI, 69 int F77_FCN (dggbak, DGGBAK) (const char* JOB, const char* SIDE,
69 double* LSCALE, double* RSCALE, int& M, 70 const int& N, const int& ILO,
70 double* V, const int& LDV, int& INFO, long, long); 71 const int& IHI, double* LSCALE,
71 72 double* RSCALE, int& M, double* V,
72 int F77_FCN( dgghrd, DGGHRD) ( const char* COMPQ, const char* COMPZ, 73 const int& LDV, int& INFO, long, long);
73 const int& N, const int& ILO, const int& IHI, double* A, const int& LDA, 74
74 double* B, const int& LDB, double* Q, const int& LDQ, double* Z, 75 int F77_FCN (dgghrd, DGGHRD) (const char* COMPQ, const char* COMPZ,
75 const int& LDZ, int& INFO, const long, const long); 76 const int& N, const int& ILO,
76 77 const int& IHI, double* A,
77 int F77_FCN( dhgeqz, DHGEQZ) ( const char* JOB, const char* COMPQ, 78 const int& LDA, double* B,
78 const char* COMPZ, const int& N, const int& ILO, const int& IHI, 79 const int& LDB, double* Q,
79 double* A, const int& LDA, double* B, const int& LDB, 80 const int& LDQ, double* Z,
80 double* ALPHAR, double* ALPHAI, double* BETA, double* Q, 81 const int& LDZ, int& INFO, long, long);
81 const int& LDQ, double* Z, const int& LDZ, double* WORK, 82
82 const int& LWORK, int& INFO, const long, const long, const long ); 83 int F77_FCN (dhgeqz, DHGEQZ) (const char* JOB, const char* COMPQ,
83 84 const char* COMPZ, const int& N,
84 int F77_FCN( dlag2, DLAG2) ( double* A, const int& LDA, double* B, 85 const int& ILO, const int& IHI,
85 const int& LDB, const double& SAFMIN, double& SCALE1, double& SCALE2, 86 double* A, const int& LDA, double* B,
86 double& WR1, double& WR2, double& WI ); 87 const int& LDB, double* ALPHAR,
88 double* ALPHAI, double* BETA, double* Q,
89 const int& LDQ, double* Z,
90 const int& LDZ, double* WORK,
91 const int& LWORK, int& INFO,
92 long, long, long);
93
94 int F77_FCN (dlag2, DLAG2) (double* A, const int& LDA, double* B,
95 const int& LDB, const double& SAFMIN,
96 double& SCALE1, double& SCALE2,
97 double& WR1, double& WR2, double& WI);
87 98
88 // Van Dooren's code (netlib.org: toms/590) for reordering 99 // Van Dooren's code (netlib.org: toms/590) for reordering
89 // GEP. Only processes Z, not Q. 100 // GEP. Only processes Z, not Q.
90 int F77_FCN( dsubsp, DSUBSP) ( const int& NMAX, const int& N, double* A, 101 int F77_FCN (dsubsp, DSUBSP) (const int& NMAX, const int& N, double* A,
91 double* B, double* Z, sort_function, const double& EPS, 102 double* B, double* Z, sort_function,
92 int& NDIM, int& FAIL, int* IND); 103 const double& EPS, int& NDIM, int& FAIL,
104 int* IND);
93 105
94 // documentation for DTGEVC incorrectly states that VR, VL are 106 // documentation for DTGEVC incorrectly states that VR, VL are
95 // complex*16; they are declared in DTGEVC as double precision 107 // complex*16; they are declared in DTGEVC as double precision
96 // (probably a cut and paste problem fro ZTGEVC) 108 // (probably a cut and paste problem fro ZTGEVC)
97 int F77_FCN( dtgevc, DTGEVC) ( const char* SIDE, const char* HOWMNY, 109 int F77_FCN (dtgevc, DTGEVC) (const char* SIDE, const char* HOWMNY,
98 int* SELECT, const int& N, double* A, const int& LDA, double* B, 110 int* SELECT, const int& N, double* A,
99 const int& LDB, double* VL, const int& LDVL, double* VR, 111 const int& LDA, double* B,
100 const int& LDVR, const int& MM, int& M, double* WORK, int& INFO, 112 const int& LDB, double* VL,
101 long, long ); 113 const int& LDVL, double* VR,
102 114 const int& LDVR, const int& MM,
103 int F77_FCN ( xdlamch, XDLAMCH) (const char* cmach, double& retval, long); 115 int& M, double* WORK, int& INFO,
104 int F77_FCN ( xdlange, XDLANGE) (const char*, const int&, 116 long, long);
117
118 int F77_FCN (xdlamch, XDLAMCH) (const char* cmach, double& retval, long);
119
120 int F77_FCN (xdlange, XDLANGE) (const char*, const int&,
105 const int&, const double*, 121 const int&, const double*,
106 const int&, double*, double&); 122 const int&, double*, double&);
107 } 123 }
108 124
109 // fcrhp, fin, fout, folhp: 125 // fcrhp, fin, fout, folhp:
112 // fin: |lambda| < 1 128 // fin: |lambda| < 1
113 // fout: |lambda| >= 1 129 // fout: |lambda| >= 1
114 // fcrhp: real(lambda) >= 0 130 // fcrhp: real(lambda) >= 0
115 // folhp: real(lambda) < 0 131 // folhp: real(lambda) < 0
116 132
117 static int fcrhp(const int& lsize, const double& alpha, 133 static int
118 const double& beta, const double& s, const double& p) 134 fcrhp (const int& lsize, const double& alpha,
135 const double& beta, const double& s, const double&)
119 { 136 {
120 if(lsize == 1) 137 if (lsize == 1)
121 return (alpha*beta >= 0 ? 1 : -1); 138 return (alpha*beta >= 0 ? 1 : -1);
122 else 139 else
123 return (s >= 0 ? 1 : -1); 140 return (s >= 0 ? 1 : -1);
124 } 141 }
125 static int fin(const int& lsize, const double& alpha, 142
126 const double& beta, const double& s, const double& p) 143 static int
144 fin (const int& lsize, const double& alpha,
145 const double& beta, const double&, const double& p)
127 { 146 {
128 int retval; 147 int retval;
129 if(lsize == 1) 148
130 retval = (fabs(alpha) < fabs(beta) ? 1 : -1); 149 if (lsize == 1)
131 else 150 retval = (fabs (alpha) < fabs (beta) ? 1 : -1);
132 retval = (fabs(p) < 1 ? 1 : -1); 151 else
133 152 retval = (fabs (p) < 1 ? 1 : -1);
134 #ifdef DEBUG 153
154 #ifdef DEBUG
135 cout << "qz: fin: retval=" << retval << endl; 155 cout << "qz: fin: retval=" << retval << endl;
136 #endif 156 #endif
157
137 return retval; 158 return retval;
138 } 159 }
139 static int folhp(const int& lsize, const double& alpha, 160
140 const double& beta, const double& s, const double& p) 161 static int
162 folhp (const int& lsize, const double& alpha,
163 const double& beta, const double& s, const double&)
141 { 164 {
142 if(lsize == 1) 165 if (lsize == 1)
143 return (alpha*beta < 0 ? 1 : -1); 166 return (alpha*beta < 0 ? 1 : -1);
144 else 167 else
145 return (s < 0 ? 1 : -1); 168 return (s < 0 ? 1 : -1);
146 } 169 }
147 static int fout(const int& lsize, const double& alpha, 170
148 const double& beta, const double& s, const double& p) 171 static int
172 fout (const int& lsize, const double& alpha,
173 const double& beta, const double&, const double& p)
149 { 174 {
150 if(lsize == 1) 175 if (lsize == 1)
151 return (fabs(alpha) >= fabs(beta) ? 1 : -1); 176 return (fabs (alpha) >= fabs (beta) ? 1 : -1);
152 else 177 else
153 return (fabs(p) >= 1 ? 1 : -1); 178 return (fabs (p) >= 1 ? 1 : -1);
154 } 179 }
155 180
156 DEFUN_DLD (qz, args, nargout, 181 DEFUN_DLD (qz, args, nargout,
157 "Usage: lambda = qz(A,B) form [1]\n\ 182 "Usage:\n\
158 [AA,BB,Q,Z{,V,W,lambda}] = qz(A,B) form [2]\n\ 183
159 [AA,BB,Z{,lambda}] = qz(A,B,opt) form [3]\n\ 184 lambda = qz (A, B) form [1]\n\
185 [AA, BB, Q, Z {, V, W, lambda}] = qz (A, B) form [2]\n\
186 [AA, BB, Z{, lambda}] = qz (A, B, opt) form [3]\n\
187 \n\
160 Generalized eigenvalue problem A x = s B x \n\ 188 Generalized eigenvalue problem A x = s B x \n\
161 189 \n\
162 Form [1]: Computes the generalized eigenvalues lambda of (A - sB).\n\ 190 Form [1]: Computes the generalized eigenvalues lambda of (A - sB).\n\
191 \n\
163 Form [2]: Computes qz decomposition, generalized eigenvectors, and \n\ 192 Form [2]: Computes qz decomposition, generalized eigenvectors, and \n\
164 generalized eigenvalues of (A - sB)\n\ 193 generalized eigenvalues of (A - sB)\n\
165 A V = B V diag(lambda)\n\ 194 A V = B V diag (lambda)\n\
166 W' A = diag(lambda) W' B\n\ 195 W' A = diag (lambda) W' B\n\
167 AA = Q'*A*Z, BB = Q'*B*Z with Q, Z orthogonal (unitary)= I\n\ 196 AA = Q'*A*Z, BB = Q'*B*Z with Q, Z orthogonal (unitary)= I\n\
197 \n\
168 Form [3]: As in form [2], but allows ordering of generalized eigenpairs\n\ 198 Form [3]: As in form [2], but allows ordering of generalized eigenpairs\n\
169 for (e.g.) solution of discrete time algebraic Riccati equations.\n\ 199 for (e.g.) solution of discrete time algebraic Riccati equations.\n\
170 Form 3 is not available for complex matrices and does not compute\n\ 200 Form 3 is not available for complex matrices and does not compute\n\
171 the generalized eigenvectors V, W, nor the orthogonal matrix Q.\n\ 201 the generalized eigenvectors V, W, nor the orthogonal matrix Q.\n\
172 \n\ 202 \n\
173 opt: for ordering eigenvalues of the GEP pencil. The leading block\n\ 203 opt: for ordering eigenvalues of the GEP pencil. The leading block\n\
174 of the revised pencil contains all eigenvalues that satisfy:\n\ 204 of the revised pencil contains all eigenvalues that satisfy:\n\
205 \n\
175 \"N\" = unordered (default) \n\ 206 \"N\" = unordered (default) \n\
176 \"S\" = small: leading block has all |lambda| <=1 \n\ 207 \"S\" = small: leading block has all |lambda| <=1 \n\
177 \"B\" = big: leading block has all |lambda >= 1 \n\ 208 \"B\" = big: leading block has all |lambda >= 1 \n\
178 \"-\" = negative real part: leading block has all eigenvalues\n\ 209 \"-\" = negative real part: leading block has all eigenvalues\n\
179 in the open left half-plant\n\ 210 in the open left half-plant\n\
181 in the closed right half-plane\n\ 212 in the closed right half-plane\n\
182 \n\ 213 \n\
183 Note: Permutation balancing is performed, but not scaling (see balance)\n\ 214 Note: Permutation balancing is performed, but not scaling (see balance)\n\
184 Order of output arguments was selected for compatibility with MATLAB\n\ 215 Order of output arguments was selected for compatibility with MATLAB\n\
185 \n\ 216 \n\
186 See also: balance, dare, eig, schur\n") 217 See also: balance, dare, eig, schur")
187 { 218 {
188 octave_value_list retval; 219 octave_value_list retval;
189 int nargin = args.length (); 220 int nargin = args.length ();
190 221
191 #ifdef DEBUG 222 #ifdef DEBUG
192 cout << "qz: nargin = " << nargin << ", nargout = " << nargout << endl; 223 cout << "qz: nargin = " << nargin << ", nargout = " << nargout << endl;
193 #endif 224 #endif
194 225
195 if (nargin < 2 || nargin > 3 || nargout > 7 ) 226 if (nargin < 2 || nargin > 3 || nargout > 7)
196 { 227 {
197 print_usage ("qz"); 228 print_usage ("qz");
198 return retval; 229 return retval;
199 } 230 }
200 else if(nargin == 3 && (nargout < 3 || nargout > 4)) 231 else if (nargin == 3 && (nargout < 3 || nargout > 4))
201 { 232 {
202 error("qz: Illegal number of output arguments for form [3] call"); 233 error ("qz: Illegal number of output arguments for form [3] call");
203 } 234 return retval;
204 235 }
205 #ifdef DEBUG 236
237 #ifdef DEBUG
206 cout << "qz: determine ordering option" << endl; 238 cout << "qz: determine ordering option" << endl;
207 #endif 239 #endif
208 240
209 // Determine ordering option 241 // Determine ordering option
210 string ord_job; 242 string ord_job;
211 static double safmin; 243 static double safmin;
212 if(nargin == 2) 244
245 if (nargin == 2)
213 ord_job = "N"; 246 ord_job = "N";
214 else if( !args(2).is_string() ) 247 else if (!args(2).is_string ())
215 error("qz: argument 3 must be a string"); 248 {
216 else 249 error ("qz: argument 3 must be a string");
217 { 250 return retval;
218 ord_job = args(2).string_value(); 251 }
219 if(ord_job[0] != 'N' && ord_job[0] != 'S' && ord_job[0] != 'B' 252 else
220 && ord_job[0] != '+' && ord_job[0] != '-') 253 {
221 error("qz: illegal order option"); 254 ord_job = args(2).string_value ();
222 255
223 // overflow constant required by dlag2 256 if (ord_job[0] != 'N'
224 F77_XFCN ( xdlamch, XDLAMCH, ("S", safmin, 1L)); 257 && ord_job[0] != 'S'
225 258 && ord_job[0] != 'B'
226 #ifdef DEBUG_EIG 259 && ord_job[0] != '+'
227 cout << "qz: initial value of safmin=" << setiosflags(ios::scientific) 260 && ord_job[0] != '-')
228 << safmin << endl; 261 {
229 #endif 262 error ("qz: illegal order option");
230 263 return retval;
231 // some machines (e.g., DEC alpha) get safmin = 0; 264 }
232 // for these, use eps instead to avoid problems in dlag2 265
233 if(safmin == 0) 266 // overflow constant required by dlag2
234 { 267 F77_FCN (xdlamch, XDLAMCH) ("S", safmin, 1L);
235 #ifdef DEBUG_EIG 268
236 cout << "qz: DANGER WILL ROBINSON: safmin is 0!" << endl; 269 #ifdef DEBUG_EIG
237 #endif 270 cout << "qz: initial value of safmin=" << setiosflags (ios::scientific)
238 271 << safmin << endl;
239 F77_XFCN ( xdlamch, XDLAMCH, ("E", safmin, 1L)); 272 #endif
240 273
241 #ifdef DEBUG_EIG 274 // some machines (e.g., DEC alpha) get safmin = 0;
242 cout << "qz: safmin set to " << setiosflags(ios::scientific) 275 // for these, use eps instead to avoid problems in dlag2
243 << safmin << endl; 276 if (safmin == 0)
244 #endif 277 {
245 } 278 #ifdef DEBUG_EIG
246 } 279 cout << "qz: DANGER WILL ROBINSON: safmin is 0!" << endl;
247 280 #endif
248 #ifdef DEBUG 281
282 F77_FCN (xdlamch, XDLAMCH) ("E", safmin, 1L);
283
284 #ifdef DEBUG_EIG
285 cout << "qz: safmin set to " << setiosflags (ios::scientific)
286 << safmin << endl;
287 #endif
288 }
289 }
290
291 #ifdef DEBUG
249 cout << "qz: check argument 1" << endl; 292 cout << "qz: check argument 1" << endl;
250 #endif 293 #endif
251 294
252 // Argument 1: check if it's o.k. dimensioned 295 // Argument 1: check if it's o.k. dimensioned
253 int nn = args(0).rows(); 296 int nn = args(0).rows ();
254 297
255 #ifdef DEBUG 298 #ifdef DEBUG
256 cout << "argument 1 dimensions: (" << nn << "," << args(0).columns() << ")" 299 cout << "argument 1 dimensions: (" << nn << "," << args(0).columns () << ")"
257 << endl; 300 << endl;
258 #endif 301 #endif
259 int arg_is_empty = empty_arg ("qz", nn, args(0).columns()); 302
303 int arg_is_empty = empty_arg ("qz", nn, args(0).columns ());
304
260 if (arg_is_empty < 0) 305 if (arg_is_empty < 0)
261 { 306 {
262 gripe_empty_arg("qz: parameter 1",0); 307 gripe_empty_arg ("qz: parameter 1", 0);
263 return retval; 308 return retval;
264 } 309 }
265 else if (arg_is_empty > 0) 310 else if (arg_is_empty > 0)
266 { 311 {
267 gripe_empty_arg("qz: parameter 1; continuing",0); 312 gripe_empty_arg ("qz: parameter 1; continuing", 0);
268 return octave_value_list (2, Matrix ()); 313 return octave_value_list (2, Matrix ());
269 } 314 }
270 else if (args(0).columns() != nn) 315 else if (args(0).columns () != nn)
271 { 316 {
272 gripe_square_matrix_required ("qz"); 317 gripe_square_matrix_required ("qz");
273 return retval; 318 return retval;
274 } 319 }
275 320
276 // Argument 1: dimensions look good; get the value 321 // Argument 1: dimensions look good; get the value
277 Matrix aa; 322 Matrix aa;
278 ComplexMatrix caa; 323 ComplexMatrix caa;
279 if (args(0).is_complex_type ()) 324
325 if (args(0).is_complex_type ())
280 caa = args(0).complex_matrix_value (); 326 caa = args(0).complex_matrix_value ();
281 else 327 else
282 aa = args(0).matrix_value (); 328 aa = args(0).matrix_value ();
283 if (error_state) 329
330 if (error_state)
284 return retval; 331 return retval;
285 332
286 #ifdef DEBUG 333 #ifdef DEBUG
287 cout << "qz: check argument 2" << endl; 334 cout << "qz: check argument 2" << endl;
288 #endif 335 #endif
289 336
290 // Extract argument 2 (bb, or cbb if complex) 337 // Extract argument 2 (bb, or cbb if complex)
291 if( (nn != args(1).columns()) || (nn != args(1).rows() )) 338 if ((nn != args(1).columns ()) || (nn != args(1).rows ()))
292 { 339 {
293 gripe_nonconformant (); 340 gripe_nonconformant ();
294 return retval; 341 return retval;
295 } 342 }
343
296 Matrix bb; 344 Matrix bb;
297 ComplexMatrix cbb; 345 ComplexMatrix cbb;
298 if (args(1).is_complex_type ()) 346
347 if (args(1).is_complex_type ())
299 cbb = args(1).complex_matrix_value (); 348 cbb = args(1).complex_matrix_value ();
300 else 349 else
301 bb = args(1).matrix_value (); 350 bb = args(1).matrix_value ();
302 if (error_state) 351
352 if (error_state)
303 return retval; 353 return retval;
304 354
305 // Both matrices loaded, now let's check what kind of arithmetic: 355 // Both matrices loaded, now let's check what kind of arithmetic:
306 //declared static to avoid compiler warnings about long jumps, vforks. 356 //declared static to avoid compiler warnings about long jumps, vforks.
307 static int complex_case 357
308 = (args(0).is_complex_type() || args(1).is_complex_type()); 358 static int complex_case
309 359 = (args(0).is_complex_type () || args(1).is_complex_type ());
310 if(nargin == 3 && complex_case) 360
311 error("qz: cannot re-order complex qz decomposition."); 361 if (nargin == 3 && complex_case)
362 {
363 error ("qz: cannot re-order complex qz decomposition.");
364 return retval;
365 }
312 366
313 // first, declare variables used in both the real and complex case 367 // first, declare variables used in both the real and complex case
314 Matrix QQ(nn,nn), ZZ(nn,nn), VR(nn,nn), VL(nn,nn); 368 Matrix QQ(nn,nn), ZZ(nn,nn), VR(nn,nn), VL(nn,nn);
315 RowVector alphar(nn), alphai(nn), betar(nn); 369 RowVector alphar(nn), alphai(nn), betar(nn);
316 370
317 ComplexMatrix CQ(nn,nn), CZ(nn,nn),CVR(nn,nn),CVL(nn,nn); 371 ComplexMatrix CQ(nn,nn), CZ(nn,nn), CVR(nn,nn), CVL(nn,nn);
318 int ilo, ihi, info; 372 int ilo, ihi, info;
319 char compq = (nargout >= 3 ? 'V' : 'N'), 373 char compq = (nargout >= 3 ? 'V' : 'N');
320 compz = (nargout >= 4 ? 'V' : 'N'); 374 char compz = (nargout >= 4 ? 'V' : 'N');
321 375
322 // initialize Q,Z to identity if we need either of them 376 // initialize Q, Z to identity if we need either of them
323 if(compq == 'V' || compz == 'V') 377 if (compq == 'V' || compz == 'V')
324 for(int ii=0; ii < nn ; ii++) 378 for (int ii = 0; ii < nn; ii++)
325 for( int jj=0; jj < nn ; jj++) 379 for (int jj = 0; jj < nn; jj++)
326 QQ(ii,jj) = ZZ(ii,jj) = (ii == jj ? 1.0 : 0.0); 380 QQ(ii,jj) = ZZ(ii,jj) = (ii == jj ? 1.0 : 0.0);
327 381
328 // always perform permutation balancing 382 // always perform permutation balancing
329 char bal_job = 'P'; 383 char bal_job = 'P';
330 RowVector lscale(nn), rscale(nn), work(6*nn); 384 RowVector lscale(nn), rscale(nn), work(6*nn);
331 385
332 if(complex_case) 386 if (complex_case)
333 error("Complex case not implemented yet"); 387 {
388 error ("Complex case not implemented yet");
389 return retval;
390 }
334 else 391 else
335 { 392 {
336 #ifdef DEBUG 393 #ifdef DEBUG
337 if(compq == 'V') 394 if (compq == 'V')
338 cout << "qz: performing balancing; QQ=" << endl << QQ << endl; 395 cout << "qz: performing balancing; QQ=" << endl << QQ << endl;
339 #endif 396 #endif
340 397
341 F77_XFCN( dggbal, DGGBAL, (&bal_job, nn, aa.fortran_vec(), 398 F77_XFCN (dggbal, DGGBAL,
342 nn, bb.fortran_vec() , nn, ilo, ihi, lscale.fortran_vec(), 399 (&bal_job, nn, aa.fortran_vec(), nn, bb.fortran_vec(),
343 rscale.fortran_vec(), work.fortran_vec(), info , 1L)); 400 nn, ilo, ihi, lscale.fortran_vec(),
344 if(f77_exception_encountered) 401 rscale.fortran_vec(), work.fortran_vec(), info, 1L));
345 (*current_liboctave_error_handler) ("unrecoverable error in qz(bal)"); 402
346 } 403 if (f77_exception_encountered)
404 {
405 error ("unrecoverable error in qz (bal)");
406 return retval;
407 }
408 }
347 409
348 // Since we just want the balancing matrices, we can use dggbal 410 // Since we just want the balancing matrices, we can use dggbal
349 // for both the real and complex cases; 411 // for both the real and complex cases;
350 // left first 412 // left first
351 if(compq == 'V') 413
352 { 414 if (compq == 'V')
353 F77_XFCN( dggbak, DGGBAK, (&bal_job, "L", 415 {
354 nn, ilo, ihi, lscale.fortran_vec(), 416 F77_XFCN (dggbak, DGGBAK,
355 rscale.fortran_vec(), nn, QQ.fortran_vec(), 417 (&bal_job, "L", nn, ilo, ihi, lscale.fortran_vec(),
356 nn, info, 1L, 1L)); 418 rscale.fortran_vec(), nn, QQ.fortran_vec(),
357 419 nn, info, 1L, 1L));
358 #ifdef DEBUG 420
359 if(compq == 'V') cout << "qz: balancing done; QQ=" << endl << QQ << endl; 421 #ifdef DEBUG
360 #endif 422 if (compq == 'V')
361 423 cout << "qz: balancing done; QQ=" << endl << QQ << endl;
362 if(f77_exception_encountered) 424 #endif
363 (*current_liboctave_error_handler) ("unrecoverable error in qz(bal-L)"); 425
426 if (f77_exception_encountered)
427 {
428 error ("unrecoverable error in qz (bal-L)");
429 return retval;
430 }
364 } 431 }
365 432
366 // then right 433 // then right
367 if(compz == 'V') 434 if (compz == 'V')
368 { 435 {
369 F77_XFCN(dggbak, DGGBAK, (&bal_job, "R", 436 F77_XFCN (dggbak, DGGBAK, (&bal_job, "R",
370 nn, ilo, ihi, lscale.fortran_vec(), 437 nn, ilo, ihi, lscale.fortran_vec(),
371 rscale.fortran_vec(), nn, ZZ.fortran_vec(), 438 rscale.fortran_vec(), nn, ZZ.fortran_vec(),
372 nn, info, 1L, 1L)); 439 nn, info, 1L, 1L));
373 440
374 #ifdef DEBUG 441 #ifdef DEBUG
375 if(compz == 'V') cout << "qz: balancing done; ZZ=" << endl << ZZ << endl; 442 if (compz == 'V')
376 #endif 443 cout << "qz: balancing done; ZZ=" << endl << ZZ << endl;
377 444 #endif
378 if(f77_exception_encountered) 445
379 (*current_liboctave_error_handler) ("unrecoverable error in qz(bal-R)"); 446 if (f77_exception_encountered)
380 } 447 {
448 error ("unrecoverable error in qz (bal-R)");
449 return retval;
450 }
451 }
381 452
382 static char qz_job; 453 static char qz_job;
383 qz_job = (nargout < 2 ? 'E' : 'S'); 454 qz_job = (nargout < 2 ? 'E' : 'S');
455
384 if (complex_case) 456 if (complex_case)
385 { 457 {
386 // complex case 458 // complex case
387 if (args(0).is_real_type ()) caa = aa; 459 if (args(0).is_real_type ())
388 if (args(1).is_real_type ()) cbb = bb; 460 caa = aa;
389 if(compq == 'V') CQ = QQ; 461
390 if(compz == 'V') CZ = ZZ; 462 if (args(1).is_real_type ())
391 error("complex case not done yet"); 463 cbb = bb;
392 } 464
465 if (compq == 'V')
466 CQ = QQ;
467
468 if (compz == 'V')
469 CZ = ZZ;
470
471 error ("complex case not done yet");
472 return retval;
473 }
393 else // real matrices case 474 else // real matrices case
394 { 475 {
395 #ifdef DEBUG 476 #ifdef DEBUG
396 cout << "qz: peforming qr decomposition of bb" << endl; 477 cout << "qz: peforming qr decomposition of bb" << endl;
397 #endif 478 #endif
398 479
399 // compute the QR factorization of bb 480 // compute the QR factorization of bb
400 QR bqr(bb); 481 QR bqr (bb);
401 482
402 #ifdef DEBUG 483 #ifdef DEBUG
403 cout << "qz: qr(bb) done; now peforming qz decomposition" << endl; 484 cout << "qz: qr (bb) done; now peforming qz decomposition" << endl;
404 #endif 485 #endif
405 486
406 bb = bqr.R(); 487 bb = bqr.R ();
407 #ifdef DEBUG 488
408 cout << "qz: extracted bb" << endl; 489 #ifdef DEBUG
409 #endif 490 cout << "qz: extracted bb" << endl;
410 491 #endif
411 aa = (bqr.Q()).transpose()*aa; 492
412 #ifdef DEBUG 493 aa = (bqr.Q ()).transpose ()*aa;
413 cout << "qz: updated aa " << endl; 494
414 cout << "bqr.Q () = " << endl << bqr.Q () << endl; 495 #ifdef DEBUG
415 if(compq == 'V') cout << "QQ =" << QQ << endl; 496 cout << "qz: updated aa " << endl;
416 #endif 497 cout << "bqr.Q () = " << endl << bqr.Q () << endl;
417 498
418 if(compq == 'V') QQ = QQ*bqr.Q(); 499 if (compq == 'V')
419 500 cout << "QQ =" << QQ << endl;
420 #ifdef DEBUG 501 #endif
421 cout << "qz: precursors done..." << endl; 502
422 #endif 503 if (compq == 'V')
423 504 QQ = QQ*bqr.Q ();
424 505
425 #ifdef DEBUG 506 #ifdef DEBUG
426 cout << "qz: compq = " << compq << ", compz = " << compz << endl; 507 cout << "qz: precursors done..." << endl;
427 #endif 508 #endif
428 509
429 // reduce to generalized hessenberg form 510 #ifdef DEBUG
430 F77_XFCN( dgghrd, DGGHRD, (&compq, &compz, nn, ilo, ihi, aa.fortran_vec(), 511 cout << "qz: compq = " << compq << ", compz = " << compz << endl;
431 nn, bb.fortran_vec(), nn, QQ.fortran_vec(), nn, ZZ.fortran_vec(), 512 #endif
432 nn, info,1L,1L)); 513
433 if(f77_exception_encountered) 514 // reduce to generalized hessenberg form
434 (*current_liboctave_error_handler) ("unrecoverable error in qz(dgghrd)"); 515 F77_XFCN (dgghrd, DGGHRD,
435 516 (&compq, &compz, nn, ilo, ihi, aa.fortran_vec(),
436 // check if just computing generalized eigenvalues or if we're 517 nn, bb.fortran_vec(), nn, QQ.fortran_vec(), nn,
437 // actually computing the decomposition 518 ZZ.fortran_vec(), nn, info, 1L, 1L));
438 519
439 // reduce to generalized Schur form 520 if (f77_exception_encountered)
440 F77_XFCN( dhgeqz, DHGEQZ, ( &qz_job, &compq, &compz, nn, ilo, ihi, 521 {
441 aa.fortran_vec(), nn, bb.fortran_vec(), nn, alphar.fortran_vec(), 522 error ("unrecoverable error in qz (dgghrd)");
442 alphai.fortran_vec(), betar.fortran_vec(), QQ.fortran_vec(), 523 return retval;
443 nn, ZZ.fortran_vec(), nn, work.fortran_vec(), nn, info, 1L, 1L, 1L)); 524 }
444 if(f77_exception_encountered) 525
445 (*current_liboctave_error_handler) ("unrecoverable error in qz(dhgeqz)"); 526 // check if just computing generalized eigenvalues or if we're
446 527 // actually computing the decomposition
447 } 528
529 // reduce to generalized Schur form
530 F77_XFCN (dhgeqz, DHGEQZ,
531 (&qz_job, &compq, &compz, nn, ilo, ihi,
532 aa.fortran_vec(), nn, bb.fortran_vec(), nn,
533 alphar.fortran_vec(), alphai.fortran_vec(),
534 betar.fortran_vec(), QQ.fortran_vec(), nn,
535 ZZ.fortran_vec(), nn, work.fortran_vec(), nn, info,
536 1L, 1L, 1L));
537
538 if (f77_exception_encountered)
539 {
540 error ("unrecoverable error in qz (dhgeqz)");
541 return retval;
542 }
543 }
448 544
449 // order the QZ decomposition? 545 // order the QZ decomposition?
450 if(ord_job[0] != 'N') 546 if (ord_job[0] != 'N')
451 { 547 {
452 if(complex_case) // probably not needed, but better be safe 548 if (complex_case)
453 error("qz: cannot re-order complex qz decomposition."); 549 {
454 550 // probably not needed, but better be safe
455 else 551 error ("qz: cannot re-order complex qz decomposition.");
456 { 552 return retval;
457 #ifdef DEBUG_SORT 553 }
458 cout << "qz: ordering eigenvalues: ord_job = " << ord_job[0] << endl; 554 else
459 #endif 555 {
460 556 #ifdef DEBUG_SORT
461 // declared static to avoid vfork/long jump compiler complaints 557 cout << "qz: ordering eigenvalues: ord_job = " << ord_job[0] << endl;
462 static sort_function sort_test; 558 #endif
463 sort_test = NULL; 559
464 560 // declared static to avoid vfork/long jump compiler complaints
465 switch(ord_job[0]) 561 static sort_function sort_test;
466 { 562 sort_test = NULL;
467 case 'S': 563
468 sort_test = &fin; 564 switch (ord_job[0])
469 break; 565 {
470 case 'B': 566 case 'S':
471 sort_test = &fout; 567 sort_test = &fin;
472 break; 568 break;
473 case '+': 569
474 sort_test = &fcrhp; 570 case 'B':
475 break; 571 sort_test = &fout;
476 case '-': 572 break;
477 sort_test = &folhp; 573
478 break; 574 case '+':
479 default: // this should never happen 575 sort_test = &fcrhp;
480 error("qz: illegal order option"); 576 break;
577
578 case '-':
579 sort_test = &folhp;
580 break;
581
582 default:
583 // illegal order option (should never happen, since we
584 // checked the options at the top).
585 panic_impossible ();
586 break;
481 } 587 }
482 588
483 int ndim, fail, ind[nn]; 589 int ndim, fail, ind[nn];
484 double inf_norm; 590 double inf_norm;
485 F77_XFCN (xdlange, XDLANGE, ("I", nn, nn, aa.fortran_vec (), nn, 591
486 work.fortran_vec (), inf_norm)); 592 F77_XFCN (xdlange, XDLANGE,
487 593 ("I", nn, nn, aa.fortran_vec (), nn,
488 double eps = DBL_EPSILON*inf_norm*nn; 594 work.fortran_vec (), inf_norm));
489 595
490 #ifdef DEBUG_SORT 596 double eps = DBL_EPSILON*inf_norm*nn;
491 cout << "qz: calling dsubsp: aa=" << endl; 597
492 octave_print_internal(cout,aa,0); 598 #ifdef DEBUG_SORT
493 cout << endl << "bb=" << endl; 599 cout << "qz: calling dsubsp: aa=" << endl;
494 octave_print_internal(cout,bb,0); 600 octave_print_internal (cout, aa, 0);
495 if(compz == 'V') 601 cout << endl << "bb=" << endl;
496 { 602 octave_print_internal (cout, bb, 0);
497 cout << endl << "ZZ=" << endl; 603 if (compz == 'V')
498 octave_print_internal(cout,ZZ,0); 604 {
499 } 605 cout << endl << "ZZ=" << endl;
500 cout << endl; 606 octave_print_internal (cout, ZZ, 0);
501 cout << "alphar = " << endl; 607 }
502 octave_print_internal(cout,(Matrix) alphar,0); 608 cout << endl;
503 cout << endl << "alphai = " << endl; 609 cout << "alphar = " << endl;
504 octave_print_internal(cout,(Matrix) alphai,0); 610 octave_print_internal (cout, (Matrix) alphar, 0);
505 cout << endl << "beta = " << endl; 611 cout << endl << "alphai = " << endl;
506 octave_print_internal(cout,(Matrix) betar,0); 612 octave_print_internal (cout, (Matrix) alphai, 0);
507 cout << endl; 613 cout << endl << "beta = " << endl;
508 #endif 614 octave_print_internal (cout, (Matrix) betar, 0);
509 615 cout << endl;
510 F77_XFCN( dsubsp, DSUBSP, (nn,nn,aa.fortran_vec(), bb.fortran_vec(), 616 #endif
511 ZZ.fortran_vec(), sort_test, eps, ndim, fail, ind)); 617
512 618 F77_XFCN (dsubsp, DSUBSP,
513 #ifdef DEBUG 619 (nn, nn, aa.fortran_vec(), bb.fortran_vec(),
514 cout << "qz: back from dsubsp: aa=" << endl; 620 ZZ.fortran_vec(), sort_test, eps, ndim, fail, ind));
515 octave_print_internal(cout,aa,0); 621
516 cout << endl << "bb=" << endl; 622 #ifdef DEBUG
517 octave_print_internal(cout,bb,0); 623 cout << "qz: back from dsubsp: aa=" << endl;
518 if(compz == 'V') 624 octave_print_internal (cout, aa, 0);
519 { 625 cout << endl << "bb=" << endl;
520 cout << endl << "ZZ=" << endl; 626 octave_print_internal (cout, bb, 0);
521 octave_print_internal(cout,ZZ,0); 627 if (compz == 'V')
522 } 628 {
523 cout << endl; 629 cout << endl << "ZZ=" << endl;
524 #endif 630 octave_print_internal (cout, ZZ, 0);
525 631 }
526 // manually update alphar, alphai, betar 632 cout << endl;
527 static int jj; 633 #endif
528 jj=0; 634
529 while(jj < nn) 635 // manually update alphar, alphai, betar
530 { 636 static int jj;
531 #ifdef DEBUG_EIG 637
532 cout << "computing gen eig #" << jj << endl; 638 jj=0;
533 #endif 639 while (jj < nn)
534 640 {
535 static int zcnt; // number of zeros in this block 641 #ifdef DEBUG_EIG
536 if(jj == (nn-1)) 642 cout << "computing gen eig #" << jj << endl;
537 zcnt = 1; 643 #endif
538 else if(aa(jj+1,jj) == 0) 644
539 zcnt = 1; 645 static int zcnt; // number of zeros in this block
540 else zcnt = 2; 646
541 647 if (jj == (nn-1))
542 if(zcnt == 1) // real zero 648 zcnt = 1;
543 { 649 else if (aa(jj+1,jj) == 0)
544 #ifdef DEBUG_EIG 650 zcnt = 1;
545 cout << " single gen eig:" << endl; 651 else zcnt = 2;
546 cout << " alphar(" << jj << ") = " << aa(jj,jj) << endl; 652
547 cout << " betar( " << jj << ") = " << bb(jj,jj) << endl; 653 if (zcnt == 1) // real zero
548 cout << " alphai(" << jj << ") = 0" << endl; 654 {
549 #endif 655 #ifdef DEBUG_EIG
550 656 cout << " single gen eig:" << endl;
551 alphar(jj) = aa(jj,jj); 657 cout << " alphar(" << jj << ") = " << aa(jj,jj) << endl;
552 alphai(jj) = 0; 658 cout << " betar( " << jj << ") = " << bb(jj,jj) << endl;
553 betar(jj) = bb(jj,jj); 659 cout << " alphai(" << jj << ") = 0" << endl;
554 } 660 #endif
555 else // complex conjugate pair 661
556 { 662 alphar(jj) = aa(jj,jj);
557 #ifdef DEBUG_EIG 663 alphai(jj) = 0;
558 cout << "qz: calling dlag2:" << endl; 664 betar(jj) = bb(jj,jj);
559 cout << "safmin=" << setiosflags(ios::scientific) << safmin << endl; 665 }
560 for(int idr = jj ; idr <= jj+1 ; idr++) 666 else
561 { 667 {
562 for(int idc = jj ; idc <= jj+1 ; idc++) 668 // complex conjugate pair
563 { 669 #ifdef DEBUG_EIG
564 cout << "aa(" << idr << "," << idc << ")=" 670 cout << "qz: calling dlag2:" << endl;
565 << aa(idr,idc) << endl; 671 cout << "safmin="
566 cout << "bb(" << idr << "," << idc << ")=" 672 << setiosflags (ios::scientific) << safmin << endl;
567 << bb(idr,idc) << endl; 673
568 } 674 for (int idr = jj; idr <= jj+1; idr++)
569 } 675 {
570 #endif 676 for (int idc = jj; idc <= jj+1; idc++)
571 double scale1, scale2, wr1, wr2, wi; 677 {
572 F77_XFCN( dlag2, DLAG2, ( &aa(jj,jj), nn, &bb(jj,jj), nn, safmin, 678 cout << "aa(" << idr << "," << idc << ")="
573 scale1, scale2, wr1, wr2, wi)); 679 << aa(idr,idc) << endl;
574 680 cout << "bb(" << idr << "," << idc << ")="
575 #ifdef DEBUG_EIG 681 << bb(idr,idc) << endl;
576 cout << "dlag2 returns: scale1=" << scale1 682 }
577 << "\tscale2=" << scale2 << endl 683 }
578 << "\twr1=" << wr1 << "\twr2=" << wr2 684 #endif
579 << "\twi=" << wi << endl; 685
580 #endif 686 double scale1, scale2, wr1, wr2, wi;
581 // just to be safe, check if it's a real pair 687 F77_XFCN (dlag2, DLAG2,
582 if(wi == 0) 688 (&aa(jj,jj), nn, &bb(jj,jj), nn, safmin,
583 { 689 scale1, scale2, wr1, wr2, wi));
584 alphar(jj) = wr1; 690
585 alphai(jj) = 0; 691 #ifdef DEBUG_EIG
586 betar(jj) = scale1; 692 cout << "dlag2 returns: scale1=" << scale1
587 alphar(jj+1) = wr2; 693 << "\tscale2=" << scale2 << endl
588 alphai(jj+1) = 0; 694 << "\twr1=" << wr1 << "\twr2=" << wr2
589 betar(jj+1) = scale2; 695 << "\twi=" << wi << endl;
590 } 696 #endif
591 else 697
592 { 698 // just to be safe, check if it's a real pair
593 alphar(jj) = alphar(jj+1)=wr1; 699 if (wi == 0)
594 alphai(jj) = -(alphai(jj+1) = wi); 700 {
595 betar(jj) = betar(jj+1) = scale1; 701 alphar(jj) = wr1;
596 } 702 alphai(jj) = 0;
597 } 703 betar(jj) = scale1;
598 704 alphar(jj+1) = wr2;
599 jj += zcnt; // advance past this block 705 alphai(jj+1) = 0;
600 } 706 betar(jj+1) = scale2;
601 707 }
602 #ifdef DEBUG_SORT 708 else
603 cout << "qz: back from dsubsp: aa=" << endl; 709 {
604 octave_print_internal(cout,aa,0); 710 alphar(jj) = alphar(jj+1)=wr1;
605 cout << endl << "bb=" << endl; 711 alphai(jj) = -(alphai(jj+1) = wi);
606 octave_print_internal(cout,bb,0); 712 betar(jj) = betar(jj+1) = scale1;
607 if(compz == 'V') 713 }
608 { 714 }
609 cout << endl << "ZZ=" << endl; 715
610 octave_print_internal(cout,ZZ,0); 716 // advance past this block
611 } 717 jj += zcnt;
612 cout << endl << "qz: ndim=" << ndim << endl << "fail=" << fail << endl; 718 }
613 cout << "alphar = " << endl; 719
614 octave_print_internal(cout,(Matrix) alphar,0); 720 #ifdef DEBUG_SORT
615 cout << endl << "alphai = " << endl; 721 cout << "qz: back from dsubsp: aa=" << endl;
616 octave_print_internal(cout,(Matrix) alphai,0); 722 octave_print_internal (cout, aa, 0);
617 cout << endl << "beta = " << endl; 723 cout << endl << "bb=" << endl;
618 octave_print_internal(cout,(Matrix) betar,0); 724 octave_print_internal (cout, bb, 0);
619 cout << endl; 725
620 #endif 726 if (compz == 'V')
621 } 727 {
622 } 728 cout << endl << "ZZ=" << endl;
623 729 octave_print_internal (cout, ZZ, 0);
730 }
731 cout << endl << "qz: ndim=" << ndim << endl
732 << "fail=" << fail << endl;
733 cout << "alphar = " << endl;
734 octave_print_internal (cout, (Matrix) alphar, 0);
735 cout << endl << "alphai = " << endl;
736 octave_print_internal (cout, (Matrix) alphai, 0);
737 cout << endl << "beta = " << endl;
738 octave_print_internal (cout, (Matrix) betar, 0);
739 cout << endl;
740 #endif
741 }
742 }
743
624 // compute generalized eigenvalues? 744 // compute generalized eigenvalues?
625 ComplexColumnVector gev; 745 ComplexColumnVector gev;
626 if(nargout < 2 || nargout == 7 || (nargin == 3 && nargout == 4)) 746
627 { 747 if (nargout < 2 || nargout == 7 || (nargin == 3 && nargout == 4))
628 if(complex_case) 748 {
629 error("complex case not yet implemented"); 749 if (complex_case)
630 else 750 {
631 { 751 error ("complex case not yet implemented");
632 #ifdef DEBUG 752 return retval;
633 cout << "qz: computing generalized eigenvalues" << endl; 753 }
634 #endif 754 else
635 755 {
636 // return finite generalized eigenvalues 756 #ifdef DEBUG
637 int ii, cnt = 0; 757 cout << "qz: computing generalized eigenvalues" << endl;
638 for( ii=0 ; ii < nn ; ii++) 758 #endif
639 if(betar(ii) != 0) 759
640 cnt++; 760 // return finite generalized eigenvalues
641 ComplexColumnVector tmp(cnt); 761 int cnt = 0;
642 for( ii=0 ; ii < nn ; ii++) 762
643 if(betar(ii) != 0) 763 for (int ii = 0; ii < nn; ii++)
644 tmp(ii) = Complex(alphar(ii), alphai(ii))/betar(ii); 764 if (betar(ii) != 0)
645 gev = tmp; 765 cnt++;
646 } 766
767 ComplexColumnVector tmp(cnt);
768
769 for (int ii = 0; ii < nn; ii++)
770 if (betar(ii) != 0)
771 tmp(ii) = Complex(alphar(ii), alphai(ii))/betar(ii);
772 gev = tmp;
773 }
774 }
775
776 // right, left eigenvector matrices
777 if (nargout >= 5)
778 {
779 char side = (nargout == 5 ? 'R' : 'B'); // which side to compute?
780 char howmny = 'B'; // compute all of them and backtransform
781 int *select = NULL; // dummy pointer; select is not used.
782 int m;
783
784 if (complex_case)
785 {
786 error ("complex type not yet implemented");
787 return retval;
788 }
789 else
790 {
791 #ifdef DEBUG
792 cout << "qz: computing generalized eigenvectors" << endl;
793 #endif
794
795 VL = QQ;
796 VR = ZZ;
797
798 F77_XFCN (dtgevc, DTGEVC,
799 (&side, &howmny, select, nn, aa.fortran_vec(),
800 nn, bb.fortran_vec(), nn, VL.fortran_vec(), nn,
801 VR.fortran_vec(), nn, nn, m, work.fortran_vec(),
802 info, 1L, 1L));
803
804 if (f77_exception_encountered)
805 {
806 error ("unrecoverable error in qz (dtgevc)");
807 return retval;
808 }
809
810 // now construct the complex form of VV, WW
811 int jj = 0;
812
813 while (jj < nn)
814 {
815 // see if real or complex eigenvalue
816 int cinc = 2; // column increment; assume complex eigenvalue
817
818 if (jj == (nn-1))
819 cinc = 1; // single column
820 else if (aa(jj+1,jj) == 0)
821 cinc = 1;
822
823 // now copy the eigenvector (s) to CVR, CVL
824 if (cinc == 1)
825 {
826 for (int ii = 0; ii < nn; ii++)
827 CVR(ii,jj) = VR(ii,jj);
828
829 if (side == 'B')
830 for (int ii = 0; ii < nn; ii++)
831 CVL(ii,jj) = VL(ii,jj);
832 }
833 else
834 {
835 // double column; complex vector
836
837 for (int ii = 0; ii < nn; ii++)
838 {
839 CVR(ii,jj) = Complex (VR(ii,jj), VR(ii,jj+1));
840 CVR(ii,jj+1) = Complex (VR(ii,jj), -VR(ii,jj+1));
841 }
842
843 if (side == 'B')
844 for (int ii = 0; ii < nn; ii++)
845 {
846 CVL(ii,jj) = Complex (VL(ii,jj), VL(ii,jj+1));
847 CVL(ii,jj+1) = Complex (VL(ii,jj), -VL(ii,jj+1));
848 }
849 }
850
851 // advance to next eigenvectors (if any)
852 jj += cinc;
853 }
854 }
855 }
856
857 switch (nargout)
858 {
859 case 7:
860 retval(6) = gev;
861
862 case 6: // return eigenvectors
863 retval(5) = CVL;
864
865 case 5: // return eigenvectors
866 retval(4) = CVR;
867
868 case 4:
869 if (nargin == 3)
870 {
871 #ifdef DEBUG
872 cout << "qz: sort: retval(3) = gev = " << endl;
873 octave_print_internal (cout, gev);
874 cout << endl;
875 #endif
876 retval(3) = gev;
877 }
878 else
879 retval(3) = ZZ;
880
881 case 3:
882 if (nargin == 3)
883 retval(2) = ZZ;
884 else
885 retval(2) = QQ;
886
887 case 2:
888 #ifdef DEBUG
889 cout << "qz: retval (1) = bb = " << endl;
890 octave_print_internal (cout, bb, 0);
891 cout << endl << "qz: retval(0) = aa = " <<endl;
892 octave_print_internal (cout, aa, 0);
893 cout << endl;
894 #endif
895 retval(1) = bb;
896 retval(0) = aa;
897 break;
898
899 case 1:
900 case 0:
901 #ifdef DEBUG
902 cout << "qz: retval(0) = gev = " << gev << endl;
903 #endif
904 retval(0) = gev;
905 break;
906
907 default:
908 error ("qz: too many return arguments.");
909 break;
647 } 910 }
648 911
649 // right, left eigenvector matrices 912 #ifdef DEBUG
650 if(nargout >= 5)
651 {
652 char side = (nargout == 5 ? 'R' : 'B'), // which side to compute?
653 howmny = 'B'; // compute all of them and backtransform
654 int *select = NULL; // dummy pointer; select is not used.
655 int m;
656
657 if(complex_case)
658 error("complex type not yet implemented");
659 else
660 {
661 #ifdef DEBUG
662 cout << "qz: computing generalized eigenvectors" << endl;
663 #endif
664
665 VL = QQ;
666 VR = ZZ;
667
668 F77_XFCN( dtgevc, DTGEVC, ( &side, &howmny, select, nn, aa.fortran_vec(),
669 nn, bb.fortran_vec(), nn, VL.fortran_vec(), nn, VR.fortran_vec(),
670 nn, nn, m, work.fortran_vec(), info, 1L, 1L ));
671 if(f77_exception_encountered)
672 (*current_liboctave_error_handler)
673 ("unrecoverable error in qz(dtgevc)");
674
675 // now construct the complex form of VV, WW
676 int jj = 0;
677 while(jj < nn)
678 {
679 // see if real or complex eigenvalue
680 int cinc = 2; // column increment; assume complex eigenvalue
681 if(jj == (nn-1))
682 cinc = 1; // single column
683 else if(aa(jj+1,jj) == 0)
684 cinc = 1;
685
686 // now copy the eigenvector(s) to CVR, CVL
687 if(cinc == 1)
688 {
689 int ii;
690 for(ii = 0; ii < nn ; ii++)
691 CVR(ii,jj) = VR(ii,jj);
692 if(side == 'B')
693 for(ii = 0; ii < nn ; ii++)
694 CVL(ii,jj) = VL(ii,jj);
695 }
696 else // double column; complex vector
697 {
698 int ii;
699 for(ii = 0; ii < nn ; ii++)
700 {
701 CVR(ii,jj) = Complex(VR(ii,jj),VR(ii,jj+1));
702 CVR(ii,jj+1) = Complex(VR(ii,jj),-VR(ii,jj+1));
703 }
704 if(side == 'B')
705 for(ii = 0; ii < nn ; ii++)
706 {
707 CVL(ii,jj) = Complex(VL(ii,jj),VL(ii,jj+1));
708 CVL(ii,jj+1) = Complex(VL(ii,jj),-VL(ii,jj+1));
709 }
710 }
711 jj += cinc; // advance to next eigenvectors (if any)
712 }
713 }
714 }
715
716 switch(nargout)
717 {
718 case 7:
719 retval(6) = gev;
720 case 6: // return eigenvectors
721 retval(5) = CVL;
722 case 5: // return eigenvectors
723 retval(4) = CVR;
724 case 4:
725 if(nargin == 3)
726 {
727 #ifdef DEBUG
728 cout << "qz: sort: retval(3) = gev = " << endl;
729 octave_print_internal(cout,gev);
730 cout << endl;
731 #endif
732 retval(3) = gev;
733 }
734 else retval(3) = ZZ;
735 case 3:
736 if(nargin == 3)
737 retval(2) = ZZ;
738 else
739 retval(2) = QQ;
740 case 2:
741 #ifdef DEBUG
742 cout << "qz: retval(1) = bb = " << endl;
743 octave_print_internal(cout,bb,0);
744 cout << endl << "qz: retval(0) = aa = " <<endl;
745 octave_print_internal(cout,aa,0);
746 cout << endl;
747 #endif
748 retval(1) = bb;
749 retval(0) = aa;
750 break;
751 case 1:
752 case 0:
753 #ifdef DEBUG
754 cout << "qz: retval(0) = gev = " << gev << endl;
755 #endif
756 retval(0) = gev;
757 break;
758 default:
759 error("qz: too many return arguments. Sorry. ");
760 }
761
762 #ifdef DEBUG
763 cout << "qz: exiting (at long last)" << endl; 913 cout << "qz: exiting (at long last)" << endl;
764 #endif 914 #endif
765 915
766 return retval; 916 return retval;
767 } 917 }
768 918
769 /* 919 /*
770 ;;; Local Variables: *** 920 ;;; Local Variables: ***