Mercurial > octave-nkf
diff src/DLD-FUNCTIONS/eig.cc @ 8339:18c4ded8612a
Add generalized eigenvalue functions
author | Jarkko Kaleva <d3roga@gmail.com> |
---|---|
date | Mon, 24 Nov 2008 10:55:50 +0100 |
parents | 87865ed7405f |
children | eb63fbe60fab |
line wrap: on
line diff
--- a/src/DLD-FUNCTIONS/eig.cc Fri Nov 21 15:03:03 2008 +0100 +++ b/src/DLD-FUNCTIONS/eig.cc Mon Nov 24 10:55:50 2008 +0100 @@ -37,7 +37,9 @@ DEFUN_DLD (eig, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {@var{lambda} =} eig (@var{a})\n\ +@deftypefnx {Loadable Function} {@var{lambda} =} eig (@var{a}, @var{b})\n\ @deftypefnx {Loadable Function} {[@var{v}, @var{lambda}] =} eig (@var{a})\n\ +@deftypefnx {Loadable Function} {[@var{v}, @var{lambda}] =} eig (@var{a}, @var{b})\n\ The eigenvalues (and eigenvectors) of a matrix are computed in a several\n\ step process which begins with a Hessenberg decomposition, followed by a\n\ Schur decomposition, from which the eigenvalues are apparent. The\n\ @@ -51,55 +53,116 @@ int nargin = args.length (); - if (nargin != 1 || nargout > 2) + if (nargin > 2 || nargin == 0 || nargout > 2) { print_usage (); return retval; } - octave_value arg = args(0); + octave_value arg_a, arg_b; + + octave_idx_type nr_a = 0, nr_b = 0; + octave_idx_type nc_a = 0, nc_b = 0; - octave_idx_type nr = arg.rows (); - octave_idx_type nc = arg.columns (); + arg_a = args(0); + nr_a = arg_a.rows (); + nc_a = arg_a.columns (); - int arg_is_empty = empty_arg ("eig", nr, nc); + int arg_is_empty = empty_arg ("eig", nr_a, nc_a); if (arg_is_empty < 0) return retval; else if (arg_is_empty > 0) return octave_value_list (2, Matrix ()); - if (nr != nc) + if (!(arg_a.is_single_type () || arg_a.is_double_type ())) + { + gripe_wrong_type_arg ("eig", arg_a); + return retval; + } + + if (nargin == 2) + { + arg_b = args(1); + nr_b = arg_b.rows (); + nc_b = arg_b.columns (); + + arg_is_empty = empty_arg ("eig", nr_b, nc_b); + if (arg_is_empty < 0) + return retval; + else if (arg_is_empty > 0) + return octave_value_list (2, Matrix ()); + + if (!(arg_b.is_single_type() || arg_b.is_double_type ())) + { + gripe_wrong_type_arg ("eig", arg_b); + return retval; + } + } + + if (nr_a != nc_a) { gripe_square_matrix_required ("eig"); return retval; } - Matrix tmp; - ComplexMatrix ctmp; - FloatMatrix ftmp; - FloatComplexMatrix fctmp; + if (nargin == 2 && nr_b != nc_b) + { + gripe_square_matrix_required ("eig"); + return retval; + } - if (arg.is_single_type ()) + Matrix tmp_a, tmp_b; + ComplexMatrix ctmp_a, ctmp_b; + FloatMatrix ftmp_a, ftmp_b; + FloatComplexMatrix fctmp_a, fctmp_b; + + if (arg_a.is_single_type ()) { FloatEIG result; - if (arg.is_real_type ()) + if (nargin == 1) { - ftmp = arg.float_matrix_value (); + if (arg_a.is_real_type ()) + { + ftmp_a = arg_a.float_matrix_value (); - if (error_state) - return retval; + if (error_state) + return retval; + else + result = FloatEIG (ftmp_a, nargout > 1); + } else - result = FloatEIG (ftmp, nargout > 1); + { + fctmp_a = arg_a.float_complex_matrix_value (); + + if (error_state) + return retval; + else + result = FloatEIG (fctmp_a, nargout > 1); + } } - else if (arg.is_complex_type ()) + else if (nargin == 2) { - fctmp = arg.float_complex_matrix_value (); + if (arg_a.is_real_type () && arg_b.is_real_type ()) + { + ftmp_a = arg_a.float_matrix_value (); + ftmp_b = arg_b.float_matrix_value (); - if (error_state) - return retval; + if (error_state) + return retval; + else + result = FloatEIG (ftmp_a, ftmp_b, nargout > 1); + } else - result = FloatEIG (fctmp, nargout > 1); + { + fctmp_a = arg_a.float_complex_matrix_value (); + fctmp_b = arg_b.float_complex_matrix_value (); + + if (error_state) + return retval; + else + result = FloatEIG (fctmp_a, fctmp_b, nargout > 1); + } } if (! error_state) @@ -123,28 +186,49 @@ { EIG result; - if (arg.is_real_type ()) - { - tmp = arg.matrix_value (); - - if (error_state) - return retval; - else - result = EIG (tmp, nargout > 1); - } - else if (arg.is_complex_type ()) + if (nargin == 1) { - ctmp = arg.complex_matrix_value (); + if (arg_a.is_real_type ()) + { + tmp_a = arg_a.matrix_value (); - if (error_state) - return retval; + if (error_state) + return retval; + else + result = EIG (tmp_a, nargout > 1); + } else - result = EIG (ctmp, nargout > 1); + { + ctmp_a = arg_a.complex_matrix_value (); + + if (error_state) + return retval; + else + result = EIG (ctmp_a, nargout > 1); + } } - else + else if (nargin == 2) { - gripe_wrong_type_arg ("eig", tmp); - return retval; + if (arg_a.is_real_type () && arg_b.is_real_type ()) + { + tmp_a = arg_a.matrix_value (); + tmp_b = arg_b.matrix_value (); + + if (error_state) + return retval; + else + result = EIG (tmp_a, tmp_b, nargout > 1); + } + else + { + ctmp_a = arg_a.complex_matrix_value (); + ctmp_b = arg_b.complex_matrix_value (); + + if (error_state) + return retval; + else + result = EIG (ctmp_a, ctmp_b, nargout > 1); + } } if (! error_state) @@ -186,9 +270,67 @@ %! assert(d, single([-1, 0; 0, 3]), sqrt (eps('single'))); %! assert(v, [-x, x; x, x], sqrt (eps('single'))); +%!test +%! A = [1, 2; -1, 1]; B = [3, 3; 1, 2]; +%! [v, d] = eig (A, B); +%! assert(A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps)); +%! assert(A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps)); + +%!test +%! A = single([1, 2; -1, 1]); B = single([3, 3; 1, 2]); +%! [v, d] = eig (A, B); +%! assert(A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps('single'))); +%! assert(A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps('single'))); + +%!test +%! A = [1, 2; 2, 1]; B = [3, -2; -2, 3]; +%! [v, d] = eig (A, B); +%! assert(A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps)); +%! assert(A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps)); + +%!test +%! A = single([1, 2; 2, 1]); B = single([3, -2; -2, 3]); +%! [v, d] = eig (A, B); +%! assert(A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps('single'))); +%! assert(A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps('single'))); + +%!test +%! A = [1+3i, 2+i; 2-i, 1+3i]; B = [5+9i, 2+i; 2-i, 5+9i]; +%! [v, d] = eig (A, B); +%! assert(A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps)); +%! assert(A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps)); + +%!test +%! A = single([1+3i, 2+i; 2-i, 1+3i]); B = single([5+9i, 2+i; 2-i, 5+9i]); +%! [v, d] = eig (A, B); +%! assert(A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps('single'))); +%! assert(A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps('single'))); + +%!test +%! A = [1+3i, 2+3i; 3-8i, 8+3i]; B = [8+i, 3+i; 4-9i, 3+i]; +%! [v, d] = eig (A, B); +%! assert(A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps)); +%! assert(A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps)); + +%!test +%! A = single([1+3i, 2+3i; 3-8i, 8+3i]); B = single([8+i, 3+i; 4-9i, 3+i]); +%! [v, d] = eig (A, B); +%! assert(A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps('single'))); +%! assert(A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps('single'))); + +%!test +%! A = [1, 2; 3, 8]; B = [8, 3; 4, 3]; +%! [v, d] = eig (A, B); +%! assert(A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps)); +%! assert(A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps)); + %!error <Invalid call to eig.*> eig (); -%!error <Invalid call to eig.*> eig ([1, 2; 3, 4], 2); +%!error <Invalid call to eig.*> eig ([1, 2; 3, 4], [4, 3; 2, 1], 1); +%!error eig ([1, 2; 3, 4], 2); %!error eig ([1, 2; 3, 4; 5, 6]); +%!error eig ("abcd"); +%!error eig ([1 2 ; 2 3], "abcd"); +%!error eig (false, [1 2 ; 2 3]); */