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