GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
eig.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1996-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include "defun.h"
31 #include "error.h"
32 #include "errwarn.h"
33 #include "ovl.h"
34 
35 #include "EIG.h"
36 #include "fEIG.h"
37 #include "oct-string.h"
38 
39 DEFUN (eig, args, nargout,
40  doc: /* -*- texinfo -*-
41 @deftypefn {} {@var{lambda} =} eig (@var{A})
42 @deftypefnx {} {@var{lambda} =} eig (@var{A}, @var{B})
43 @deftypefnx {} {[@var{V}, @var{lambda}] =} eig (@var{A})
44 @deftypefnx {} {[@var{V}, @var{lambda}] =} eig (@var{A}, @var{B})
45 @deftypefnx {} {[@var{V}, @var{lambda}, @var{W}] =} eig (@var{A})
46 @deftypefnx {} {[@var{V}, @var{lambda}, @var{W}] =} eig (@var{A}, @var{B})
47 @deftypefnx {} {[@dots{}] =} eig (@var{A}, @var{balanceOption})
48 @deftypefnx {} {[@dots{}] =} eig (@var{A}, @var{B}, @var{algorithm})
49 @deftypefnx {} {[@dots{}] =} eig (@dots{}, @var{eigvalOption})
50 Compute the eigenvalues (@var{lambda}) and optionally the right eigenvectors
51 (@var{V}) and the left eigenvectors (@var{W}) of a matrix or pair of matrices.
52 
53 The flag @var{balanceOption} can be one of:
54 
55 @table @asis
56 @item @qcode{"balance"} (default)
57 Preliminary balancing is on.
58 
59 @item @qcode{"nobalance"}
60 Disables preliminary balancing.
61 @end table
62 
63 The flag @var{eigvalOption} can be one of:
64 
65 @table @asis
66 @item @qcode{"matrix"}
67 Return the eigenvalues in a diagonal matrix. (default if 2 or 3 outputs
68 are requested)
69 
70 @item @qcode{"vector"}
71 Return the eigenvalues in a column vector. (default if only 1 output is
72 requested, e.g., @var{lambda} = eig (@var{A}))
73 @end table
74 
75 The flag @var{algorithm} can be one of:
76 
77 @table @asis
78 @item @qcode{"chol"}
79 Use the Cholesky factorization of B. (default if @var{A} is symmetric
80 (Hermitian) and @var{B} is symmetric (Hermitian) positive definite)
81 
82 @item @qcode{"qz"}
83 Use the QZ algorithm. (used whenever @var{A} or @var{B} are not symmetric)
84 @end table
85 
86 @multitable @columnfractions .31 .23 .23 .23
87 @headitem @tab no flag @tab chol @tab qz
88 @item both are symmetric
89 @tab @qcode{"chol"}
90 @tab @qcode{"chol"}
91 @tab @qcode{"qz"}
92 @item at least one is not symmetric
93 @tab @qcode{"qz"}
94 @tab @qcode{"qz"}
95 @tab @qcode{"qz"}
96 @end multitable
97 
98 The eigenvalues returned by @code{eig} are not ordered.
99 @seealso{eigs, svd}
100 @end deftypefn */)
101 {
102  int nargin = args.length ();
103 
104  if (nargin > 4 || nargin == 0)
105  print_usage ();
106 
108 
109  octave_value arg_a, arg_b;
110 
111  arg_a = args(0);
112 
113  if (arg_a.isempty ())
114  return octave_value_list (2, Matrix ());
115 
116  if (! arg_a.isfloat ())
117  err_wrong_type_arg ("eig", arg_a);
118 
119  if (arg_a.rows () != arg_a.columns ())
120  err_square_matrix_required ("eig", "A");
121 
122  // determine if it's AEP or GEP
123  bool AEPcase = nargin == 1 || args(1).is_string ();
124 
125  if (! AEPcase)
126  {
127  arg_b = args(1);
128 
129  if (arg_b.isempty ())
130  return octave_value_list (2, Matrix ());
131 
132  if (! arg_b.isfloat ())
133  err_wrong_type_arg ("eig", arg_b);
134 
135  if (arg_b.rows () != arg_b.columns ())
136  err_square_matrix_required ("eig", "B");
137  }
138 
139  bool qz_flag = false;
140  bool chol_flag = false;
141  bool balance_flag = false;
142  bool no_balance_flag = false;
143  bool matrix_flag = false;
144  bool vector_flag = false;
145 
146  for (int i = (AEPcase ? 1 : 2); i < args.length (); ++i)
147  {
148  if (! args(i).is_string ())
149  err_wrong_type_arg ("eig", args(i));
150 
151  std::string arg_i = args(i).string_value ();
152  if (octave::string::strcmpi (arg_i, "qz"))
153  qz_flag = true;
154  else if (octave::string::strcmpi (arg_i, "chol"))
155  chol_flag = true;
156  else if (octave::string::strcmpi (arg_i, "balance"))
157  balance_flag = true;
158  else if (octave::string::strcmpi (arg_i, "nobalance"))
159  no_balance_flag = true;
160  else if (octave::string::strcmpi (arg_i, "matrix"))
161  matrix_flag = true;
162  else if (octave::string::strcmpi (arg_i, "vector"))
163  vector_flag = true;
164  else
165  error (R"(eig: invalid option "%s")", arg_i.c_str ());
166  }
167 
168  if (balance_flag && no_balance_flag)
169  error (R"(eig: "balance" and "nobalance" options are mutually exclusive)");
170  if (vector_flag && matrix_flag)
171  error (R"(eig: "vector" and "matrix" options are mutually exclusive)");
172  if (qz_flag && chol_flag)
173  error (R"(eig: "qz" and "chol" options are mutually exclusive)");
174 
175  if (AEPcase)
176  {
177  if (qz_flag)
178  error (R"(eig: invalid "qz" option for algebraic eigenvalue problem)");
179  if (chol_flag)
180  error (R"(eig: invalid "chol" option for algebraic eigenvalue problem)");
181  }
182  else
183  {
184  if (balance_flag)
185  error (R"(eig: invalid "balance" option for generalized eigenvalue problem)");
186  if (no_balance_flag)
187  error (R"(eig: invalid "nobalance" option for generalized eigenvalue problem)");
188  }
189 
190  // Default is to balance
191  const bool balance = (no_balance_flag ? false : true);
192  const bool force_qz = qz_flag;
193 
194 
195  Matrix tmp_a, tmp_b;
196  ComplexMatrix ctmp_a, ctmp_b;
197  FloatMatrix ftmp_a, ftmp_b;
198  FloatComplexMatrix fctmp_a, fctmp_b;
199 
200  if (arg_a.is_single_type ())
201  {
202  FloatEIG result;
203  if (AEPcase)
204  {
205  if (arg_a.isreal ())
206  {
207  ftmp_a = arg_a.float_matrix_value ();
208 
209  result = FloatEIG (ftmp_a, nargout > 1, nargout > 2, balance);
210  }
211  else
212  {
213  fctmp_a = arg_a.float_complex_matrix_value ();
214 
215  result = FloatEIG (fctmp_a, nargout > 1, nargout > 2, balance);
216  }
217  }
218  else
219  {
220  if (arg_a.isreal () && arg_b.isreal ())
221  {
222  ftmp_a = arg_a.float_matrix_value ();
223  ftmp_b = arg_b.float_matrix_value ();
224 
225  result = FloatEIG (ftmp_a, ftmp_b, nargout > 1, nargout > 2,
226  force_qz);
227  }
228  else
229  {
230  fctmp_a = arg_a.float_complex_matrix_value ();
231  fctmp_b = arg_b.float_complex_matrix_value ();
232 
233  result = FloatEIG (fctmp_a, fctmp_b, nargout > 1, nargout > 2,
234  force_qz);
235  }
236  }
237 
238  if (nargout == 0 || nargout == 1)
239  {
240  if (matrix_flag)
242  else
243  retval = ovl (result.eigenvalues ());
244  }
245  else if (nargout == 2)
246  {
247  if (vector_flag)
248  retval = ovl (result.right_eigenvectors (), result.eigenvalues ());
249  else
250  retval = ovl (result.right_eigenvectors (),
251  FloatComplexDiagMatrix (result.eigenvalues ()));
252  }
253  else
254  {
255  if (vector_flag)
256  retval = ovl (result.right_eigenvectors (),
257  result.eigenvalues (),
258  result.left_eigenvectors ());
259  else
260  retval = ovl (result.right_eigenvectors (),
262  result.left_eigenvectors ());
263  }
264  }
265  else
266  {
267  EIG result;
268 
269  if (AEPcase)
270  {
271  if (arg_a.isreal ())
272  {
273  tmp_a = arg_a.matrix_value ();
274 
275  result = EIG (tmp_a, nargout > 1, nargout > 2, balance);
276  }
277  else
278  {
279  ctmp_a = arg_a.complex_matrix_value ();
280 
281  result = EIG (ctmp_a, nargout > 1, nargout > 2, balance);
282  }
283  }
284  else
285  {
286  if (arg_a.isreal () && arg_b.isreal ())
287  {
288  tmp_a = arg_a.matrix_value ();
289  tmp_b = arg_b.matrix_value ();
290 
291  result = EIG (tmp_a, tmp_b, nargout > 1, nargout > 2, force_qz);
292  }
293  else
294  {
295  ctmp_a = arg_a.complex_matrix_value ();
296  ctmp_b = arg_b.complex_matrix_value ();
297 
298  result = EIG (ctmp_a, ctmp_b, nargout > 1, nargout > 2, force_qz);
299  }
300  }
301 
302  if (nargout == 0 || nargout == 1)
303  {
304  if (matrix_flag)
305  retval = ovl (ComplexDiagMatrix (result.eigenvalues ()));
306  else
307  retval = ovl (result.eigenvalues ());
308  }
309  else if (nargout == 2)
310  {
311  if (vector_flag)
312  retval = ovl (result.right_eigenvectors (), result.eigenvalues ());
313  else
314  retval = ovl (result.right_eigenvectors (),
315  ComplexDiagMatrix (result.eigenvalues ()));
316  }
317  else
318  {
319  if (vector_flag)
320  retval = ovl (result.right_eigenvectors (),
321  result.eigenvalues (),
322  result.left_eigenvectors ());
323  else
324  retval = ovl (result.right_eigenvectors (),
325  ComplexDiagMatrix (result.eigenvalues ()),
326  result.left_eigenvectors ());
327  }
328  }
329 
330  return retval;
331 }
332 
333 /*
334 %!assert (eig ([1, 2; 2, 1]), [-1; 3], sqrt (eps))
335 
336 %!test
337 %! [v, d] = eig ([1, 2; 2, 1]);
338 %! x = 1 / sqrt (2);
339 %! assert (d, [-1, 0; 0, 3], sqrt (eps))
340 %! assert (v, [-x, x; x, x], sqrt (eps))
341 
342 %!test
343 %! [v, d, w] = eig ([1, 2; 2, 1]);
344 %! x = 1 / sqrt (2);
345 %! assert (w, [-x, x; x, x], sqrt (eps))
346 
347 %!test
348 %! [v, d] = eig ([1, 2; 2, 1], "balance");
349 %! x = 1 / sqrt (2);
350 %! assert (d, [-1, 0; 0, 3], sqrt (eps))
351 %! assert (v, [-x, x; x, x], sqrt (eps))
352 
353 %!test
354 %! [v, d, w] = eig ([1, 2; 2, 1], "balance");
355 %! x = 1 / sqrt (2);
356 %! assert (w, [-x, x; x, x], sqrt (eps));
357 
358 %!assert (eig (single ([1, 2; 2, 1])), single ([-1; 3]), sqrt (eps ("single")))
359 
360 %!assert (eig (single ([1, 2; 2, 1]), "balance"),
361 %! single ([-1; 3]), sqrt (eps ("single")))
362 
363 %!test
364 %! [v, d] = eig (single ([1, 2; 2, 1]));
365 %! x = single (1 / sqrt (2));
366 %! assert (d, single ([-1, 0; 0, 3]), sqrt (eps ("single")))
367 %! assert (v, [-x, x; x, x], sqrt (eps ("single")))
368 
369 %!test
370 %! [v, d, w] = eig (single ([1, 2; 2, 1]));
371 %! x = single (1 / sqrt (2));
372 %! assert (w, [-x, x; x, x], sqrt (eps ("single")))
373 
374 %!test
375 %! [v, d] = eig (single ([1, 2; 2, 1]), "balance");
376 %! x = single (1 / sqrt (2));
377 %! assert (d, single ([-1, 0; 0, 3]), sqrt (eps ("single")));
378 %! assert (v, [-x, x; x, x], sqrt (eps ("single")))
379 
380 %!test
381 %! [v, d, w] = eig (single ([1, 2; 2, 1]), "balance");
382 %! x = single (1 / sqrt (2));
383 %! assert (w, [-x, x; x, x], sqrt (eps ("single")))
384 
385 
386 ## If (at least one of) the matrices are non-symmetric,
387 ## regardless the algorithm flag the qz algorithm should be used.
388 ## So the results without algorithm flag, with "qz" and with "chol"
389 ## should be the same.
390 %!function nonsym_chol_2_output (A, B, res = sqrt (eps))
391 %! [v, d] = eig (A, B);
392 %! [v2, d2] = eig (A, B, "qz");
393 %! [v3, d3] = eig (A, B, "chol");
394 %! assert (A * v(:, 1), d(1, 1) * B * v(:, 1), res)
395 %! assert (A * v(:, 2), d(2, 2) * B * v(:, 2), res)
396 %! assert (v, v2)
397 %! assert (v, v3)
398 %! assert (d, d2)
399 %! assert (d, d3)
400 %!endfunction
401 
402 %!test nonsym_chol_2_output ([1, 2; -1, 1], [3, 3; 1, 2])
403 %!test nonsym_chol_2_output ([1+3i, 2+3i; 3-8i, 8+3i], [8+i, 3+i; 4-9i, 3+i])
404 %!test nonsym_chol_2_output ([1, 2; 3, 8], [8, 3; 4, 3])
405 
406 %!test nonsym_chol_2_output (single ([1, 2; -1, 1]),
407 %! single ([3, 3; 1, 2]), sqrt (eps ("single")))
408 %!test nonsym_chol_2_output (single ([1+3i, 2+3i; 3-8i, 8+3i]),
409 %! single ([8+i, 3+i; 4-9i, 3+i]),
410 %! sqrt (eps ("single")))
411 
412 %!function nonsym_chol_3_output (A, B, res = sqrt (eps))
413 %! [v, d, w] = eig (A, B);
414 %! [v2, d2, w2] = eig (A, B, "qz");
415 %! [v3, d3, w3] = eig (A, B, "chol");
416 %! wt = w';
417 %! assert (wt(1, :)* A, d(1, 1) * wt(1, :) * B, res)
418 %! assert (wt(2, :)* A, d(2, 2) * wt(2, :) * B, res)
419 %! assert (v, v2)
420 %! assert (v, v3)
421 %! assert (d, d2)
422 %! assert (d, d3)
423 %! assert (w, w2)
424 %! assert (w, w3)
425 %!endfunction
426 
427 %!test nonsym_chol_3_output ([1, 2; -1, 1], [3, 3; 1, 2])
428 %!test nonsym_chol_3_output ([1+3i, 2+3i; 3-8i, 8+3i], [8+i, 3+i; 4-9i, 3+i])
429 %!test nonsym_chol_3_output ([1, 2; 3, 8], [8, 3; 4, 3])
430 
431 %!test nonsym_chol_3_output (single ([1, 2; -1, 1]),
432 %! single ([3, 3; 1, 2]), sqrt (eps ("single")))
433 %!test nonsym_chol_3_output (single ([1+3i, 2+3i; 3-8i, 8+3i]),
434 %! single ([8+i, 3+i; 4-9i, 3+i]),
435 %! sqrt (eps ("single")))
436 
437 ## If the matrices are symmetric,
438 ## then the chol method is default.
439 ## So the results without algorithm flag and with "chol" should be the same.
440 %!function sym_chol_2_input (A, B, res = sqrt (eps))
441 %! [v, d] = eig (A, B);
442 %! [v2, d2] = eig (A, B, "chol");
443 %! assert (A * v(:, 1), d(1, 1) * B * v(:, 1), res)
444 %! assert (A * v(:, 2), d(2, 2) * B * v(:, 2), res)
445 %! assert (v, v2)
446 %! assert (d, d2)
447 %!endfunction
448 
449 %!test sym_chol_2_input ([1, 2; 2, 1], [3, -2; -2, 3])
450 %!test sym_chol_2_input ([1+3i, 2+i; 2-i, 1+3i], [5+9i, 2+i; 2-i, 5+9i])
451 %!test sym_chol_2_input ([1, 1+i; 1-i, 1], [2, 0; 0, 2])
452 
453 %!test sym_chol_2_input (single ([1, 2; 2, 1]), single ([3, -2; -2, 3]),
454 %! sqrt (eps ("single")))
455 %!test sym_chol_2_input (single ([1+3i, 2+i; 2-i, 1+3i]),
456 %! single ([5+9i, 2+i; 2-i, 5+9i]), sqrt (eps ("single")))
457 %!test sym_chol_2_input (single ([1, 1+i; 1-i, 1]), single ([2, 0; 0, 2]),
458 %! sqrt (eps ("single")))
459 
460 %!function sym_chol_3_input (A, B, res = sqrt (eps))
461 %! [v, d, w] = eig (A, B);
462 %! [v2, d2, w2] = eig (A, B, "chol");
463 %! wt = w';
464 %! assert (wt(1, :)* A, d(1, 1) * wt(1, :) * B, res)
465 %! assert (wt(2, :)* A, d(2, 2) * wt(2, :) * B, res)
466 %! assert (v, v2)
467 %! assert (d, d2)
468 %! assert (w, w2)
469 %!endfunction
470 
471 %!test sym_chol_3_input ([1, 2; 2, 1], [3, -2; -2, 3])
472 %!test sym_chol_3_input ([1+3i, 2+i; 2-i, 1+3i], [5+9i, 2+i; 2-i, 5+9i])
473 %!test sym_chol_3_input ([1, 1+i; 1-i, 1], [2, 0; 0, 2])
474 
475 %!test sym_chol_3_input (single ([1, 2; 2, 1]), single ([3, -2; -2, 3]),
476 %! sqrt (eps ("single")))
477 %!test sym_chol_3_input (single ([1+3i, 2+i; 2-i, 1+3i]),
478 %! single ([5+9i, 2+i; 2-i, 5+9i]), sqrt (eps ("single")))
479 %!test sym_chol_3_input (single ([1, 1+i; 1-i, 1]), single ([2, 0; 0, 2]),
480 %! sqrt (eps ("single")))
481 
482 ## "balance" is always default
483 ## so the results with and without "balance" should be the same
484 ## while in this case "nobalance" should produce different result
485 %!test
486 %! A = [3 -2 -0.9 0; -2 4 1 -0; -0 0 -1 0; -0.5 -0.5 0.1 1];
487 %! [V1, D1] = eig (A);
488 %! [V2, D2] = eig (A, "balance");
489 %! [V3, D3] = eig (A, "nobalance");
490 %! assert (V1, V2)
491 %! assert (D1, D2)
492 %! assert (isequal (V2, V3), false)
493 
494 ## Testing the flags in all combination.
495 ## If 2 flags are on, than the result should be the same regardless
496 ## of the flags order.
497 ## option1 represents the first order while option2 represents the other order.
498 ## d and d2 should be a diagonal matrix if "matrix" flag is on while
499 ## these should be column vectors if the "vector" flag is on.
500 %!function test_eig_args (args, options1, options2, testd = @() true)
501 %! [v, d, w] = eig (args{:}, options1{:});
502 %! [v2, d2, w2] = eig (args{:}, options2{:});
503 %! assert (testd (d))
504 %! assert (testd (d2))
505 %! assert (v, v2)
506 %! assert (d, d2)
507 %! assert (w, w2)
508 %!endfunction
509 
510 %!function qz_chol_with_shapes (A, B)
511 %! for shapes = struct ("name", {"vector", "matrix"},
512 %! "test", {@isvector, @isdiag})
513 %! test_eig_args ({A, B}, {"qz", shapes.name},
514 %! {shapes.name, "qz"}, shapes.test);
515 %! test_eig_args ({A, B}, {"chol", shapes.name},
516 %! {shapes.name, "chol"}, shapes.test);
517 %! endfor
518 %!endfunction
519 
520 %!function balance_nobalance_with_shapes (A)
521 %! for shapes = struct ("name", {"vector", "matrix"},
522 %! "test", {@isvector, @isdiag})
523 %! test_eig_args ({A}, {"balance", shapes.name},
524 %! {shapes.name, "balance"}, shapes.test);
525 %! test_eig_args ({A}, {"nobalance", shapes.name},
526 %! {shapes.name, "nobalance"}, shapes.test);
527 %! endfor
528 %!endfunction
529 
530 ## Default return format:
531 ## diagonal matrix if 2 or 3 outputs are specified
532 ## column vector if 1 output is specified
533 %!function test_shapes (args)
534 %! d = eig (args{:});
535 %! assert (isvector(d))
536 %! d2 = eig (args{:}, "vector");
537 %! assert (isvector(d2))
538 %! [v, d3] = eig (args{:});
539 %! assert (isdiag(d3))
540 %! d4 = eig (args{:}, "matrix");
541 %! assert (isdiag(d4))
542 %! [v, d5, w] = eig (args{:});
543 %! assert (isdiag(d5))
544 %! d6 = eig (args{:}, "matrix");
545 %! assert (isdiag(d6))
546 %! assert (d, d2)
547 %! assert (d3, d4)
548 %! assert (d5, d6)
549 %! assert (d, diag(d3))
550 %! assert (d, diag(d5))
551 %!endfunction
552 
553 %!function shapes_AEP (A)
554 %! test_shapes({A});
555 %!endfunction
556 
557 %!function shapes_GEP (A, B)
558 %! test_shapes({A, B});
559 %!endfunction
560 
561 %!test balance_nobalance_with_shapes ([1, 2; 2, 1]);
562 %!test balance_nobalance_with_shapes (single ([1, 2; 2, 1]));
563 
564 %!test shapes_AEP ([1, 2; 2, 1]);
565 %!test shapes_AEP (single ([1, 2; 2, 1]));
566 
567 %!test qz_chol_with_shapes ([1, 1+i; 1-i, 1], [2, 0; 0, 2]);
568 %!test qz_chol_with_shapes ([1, 2; 3, 8], [8, 3; 4, 3]);
569 %!test qz_chol_with_shapes ([1, 2; -1, 1], [3, 3; 1, 2]);
570 
571 %!test qz_chol_with_shapes (single ([1, 1+i; 1-i, 1]), single ([2, 0; 0, 2]));
572 %!test qz_chol_with_shapes (single ([1, 2; 3, 8]), single ([8, 3; 4, 3]));
573 %!test qz_chol_with_shapes (single ([1, 2; -1, 1]), single ([3, 3; 1, 2]));
574 
575 %!test shapes_GEP ([1, 1+i; 1-i, 1], [2, 0; 0, 2]);
576 %!test shapes_GEP ([1, 2; 3, 8], [8, 3; 4, 3]);
577 %!test shapes_GEP ([1, 2; -1, 1], [3, 3; 1, 2]);
578 
579 %!test shapes_GEP (single ([1, 1+i; 1-i, 1]), single ([2, 0; 0, 2]));
580 %!test shapes_GEP (single ([1, 2; 3, 8]), single ([8, 3; 4, 3]));
581 %!test shapes_GEP (single ([1, 2; -1, 1]), single ([3, 3; 1, 2]));
582 
583 ## Check if correct default method is used for symmetric input
584 %!function chol_qz_accuracy (A, B, is_qz_accurate, is_chol_accurate)
585 %! [V1, D1] = eig (A, B, 'qz');
586 %! [V2, D2] = eig (A, B); #default is chol
587 %! assert (isequal (A*V1, A*V1*D1), is_qz_accurate)
588 %! assert (isequal (A*V2, A*V2*D2), is_chol_accurate)
589 %!endfunction
590 %!test
591 %! minij_100 = gallery ('minij', 100);
592 %! chol_qz_accuracy (minij_100, minij_100, false, true);
593 %! moler_100 = gallery ('moler', 100);
594 %! chol_qz_accuracy (moler_100, moler_100, false, true);
595 %! A = diag([1e-16, 1e-15]);
596 %! chol_qz_accuracy (A, A, true, false);
597 
598 %!error eig ()
599 %!error eig (false)
600 %!error eig ([1, 2; 3, 4], [4, 3; 2, 1], 1)
601 
602 %!error <EIG requires same size matrices>
603 %! eig ([1, 2; 3, 4], 2)
604 %!error <must be a square matrix>
605 %! eig ([1, 2; 3, 4; 5, 6])
606 %!error <wrong type argument>
607 %! eig ("abcd")
608 %!error <invalid option "abcd">
609 %! eig ([1 2 ; 2 3], "abcd")
610 %!error <invalid "chol" option for algebraic eigenvalue problem>
611 %! eig ([1 2 ; 2 3], "chol")
612 %!error <invalid "qz" option for algebraic eigenvalue problem>
613 %! eig ([1 2 ; 2 3], "qz")
614 %!error <wrong type argument>
615 %! eig (false, [1 2 ; 2 3])
616 %!error <invalid option "abcd">
617 %! eig ([1 2 ; 2 3], [1 2 ; 2 3], "abcd")
618 %!error <invalid "qz" option for algebraic eigenvalue problem>
619 %! eig ([1 2 ; 2 3], "balance", "qz")
620 %!error <invalid option "abcd">
621 %! eig ([1 2 ; 2 3], [1 2 ; 2 3], "vector", "abcd")
622 %!error <invalid option "abcd">
623 %! eig ([1 2 ; 2 3], "balance", "matrix", "abcd")
624 %!error <"balance" and "nobalance" options are mutually exclusive>
625 %! eig ([1 2 ; 2 3], "balance", "nobalance")
626 %!error <"balance" and "nobalance" options are mutually exclusive>
627 %! eig ([1 2 ; 2 3], "nobalance", "balance")
628 %!error <"vector" and "matrix" options are mutually exclusive>
629 %! eig ([1 2 ; 2 3], "matrix", "vector")
630 %!error <"vector" and "matrix" options are mutually exclusive>
631 %! eig ([1 2 ; 2 3], "vector", "matrix")
632 %!error <"vector" and "matrix" options are mutually exclusive>
633 %! eig ([1 2 ; 2 3], [1 2 ; 2 3], "matrix", "vector")
634 %!error <"vector" and "matrix" options are mutually exclusive>
635 %! eig ([1 2 ; 2 3], [1 2 ; 2 3], "vector", "matrix")
636 %!error <wrong type argument>
637 %! eig ([1 2 ; 2 3], [1 2 ; 2 3], false)
638 %!error <wrong type argument>
639 %! eig ([1 2 ; 2 3], [1 2 ; 2 3], [1 2 ; 2 3])
640 */
Definition: EIG.h:41
ComplexMatrix right_eigenvectors(void) const
Definition: EIG.h:122
ComplexColumnVector eigenvalues(void) const
Definition: EIG.h:121
ComplexMatrix left_eigenvectors(void) const
Definition: EIG.h:123
Definition: fEIG.h:41
FloatComplexColumnVector eigenvalues(void) const
Definition: fEIG.h:121
FloatComplexMatrix left_eigenvectors(void) const
Definition: fEIG.h:123
FloatComplexMatrix right_eigenvectors(void) const
Definition: fEIG.h:122
Definition: dMatrix.h:42
bool isreal(void) const
Definition: ov.h:691
ComplexMatrix complex_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:824
octave_idx_type rows(void) const
Definition: ov.h:504
octave_idx_type columns(void) const
Definition: ov.h:506
FloatMatrix float_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:809
bool isempty(void) const
Definition: ov.h:557
bool is_single_type(void) const
Definition: ov.h:651
Matrix matrix_value(bool frc_str_conv=false) const
Definition: ov.h:806
FloatComplexMatrix float_complex_matrix_value(bool frc_str_conv=false) const
Definition: ov.h:828
bool isfloat(void) const
Definition: ov.h:654
OCTINTERP_API void print_usage(void)
Definition: defun.cc:53
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:56
void error(const char *fmt,...)
Definition: error.cc:968
void err_square_matrix_required(const char *fcn, const char *name)
Definition: errwarn.cc:122
void err_wrong_type_arg(const char *name, const char *s)
Definition: errwarn.cc:166
bool strcmpi(const T &str_a, const T &str_b)
True if strings are the same, ignoring case.
Definition: oct-string.cc:139
octave_value::octave_value(const Array< char > &chm, char type) return retval
Definition: ov.cc:811
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:211