eig.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1996-2012 John W. Eaton
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 
00027 #include "EIG.h"
00028 #include "fEIG.h"
00029 
00030 #include "defun-dld.h"
00031 #include "error.h"
00032 #include "gripes.h"
00033 #include "oct-obj.h"
00034 #include "utils.h"
00035 
00036 DEFUN_DLD (eig, args, nargout,
00037   "-*- texinfo -*-\n\
00038 @deftypefn  {Loadable Function} {@var{lambda} =} eig (@var{A})\n\
00039 @deftypefnx {Loadable Function} {@var{lambda} =} eig (@var{A}, @var{B})\n\
00040 @deftypefnx {Loadable Function} {[@var{V}, @var{lambda}] =} eig (@var{A})\n\
00041 @deftypefnx {Loadable Function} {[@var{V}, @var{lambda}] =} eig (@var{A}, @var{B})\n\
00042 Compute the eigenvalues and eigenvectors of a matrix.\n\
00043 \n\
00044 Eigenvalues are computed in a several step process which begins with a\n\
00045 Hessenberg decomposition, followed by a Schur@tie{}decomposition, from which\n\
00046 the eigenvalues are apparent.  The eigenvectors, when desired, are computed\n\
00047 by further manipulations of the Schur@tie{}decomposition.\n\
00048 \n\
00049 The eigenvalues returned by @code{eig} are not ordered.\n\
00050 @seealso{eigs, svd}\n\
00051 @end deftypefn")
00052 {
00053   octave_value_list retval;
00054 
00055   int nargin = args.length ();
00056 
00057   if (nargin > 2 || nargin == 0 || nargout > 2)
00058     {
00059       print_usage ();
00060       return retval;
00061     }
00062 
00063   octave_value arg_a, arg_b;
00064 
00065   octave_idx_type nr_a = 0, nr_b = 0;
00066   octave_idx_type nc_a = 0, nc_b = 0;
00067 
00068   arg_a = args(0);
00069   nr_a = arg_a.rows ();
00070   nc_a = arg_a.columns ();
00071 
00072   int arg_is_empty = empty_arg ("eig", nr_a, nc_a);
00073   if (arg_is_empty < 0)
00074     return retval;
00075   else if (arg_is_empty > 0)
00076     return octave_value_list (2, Matrix ());
00077 
00078   if (!(arg_a.is_single_type () || arg_a.is_double_type ()))
00079     {
00080       gripe_wrong_type_arg ("eig", arg_a);
00081       return retval;
00082     }
00083 
00084   if (nargin == 2)
00085     {
00086       arg_b = args(1);
00087       nr_b = arg_b.rows ();
00088       nc_b = arg_b.columns ();
00089 
00090       arg_is_empty = empty_arg ("eig", nr_b, nc_b);
00091       if (arg_is_empty < 0)
00092         return retval;
00093       else if (arg_is_empty > 0)
00094         return octave_value_list (2, Matrix ());
00095 
00096       if (!(arg_b.is_single_type() || arg_b.is_double_type ()))
00097         {
00098           gripe_wrong_type_arg ("eig", arg_b);
00099           return retval;
00100         }
00101     }
00102 
00103   if (nr_a != nc_a)
00104     {
00105       gripe_square_matrix_required ("eig");
00106       return retval;
00107     }
00108 
00109   if (nargin == 2 && nr_b != nc_b)
00110     {
00111       gripe_square_matrix_required ("eig");
00112       return retval;
00113     }
00114 
00115   Matrix tmp_a, tmp_b;
00116   ComplexMatrix ctmp_a, ctmp_b;
00117   FloatMatrix ftmp_a, ftmp_b;
00118   FloatComplexMatrix fctmp_a, fctmp_b;
00119 
00120   if (arg_a.is_single_type ())
00121     {
00122       FloatEIG result;
00123 
00124       if (nargin == 1)
00125         {
00126           if (arg_a.is_real_type ())
00127             {
00128               ftmp_a = arg_a.float_matrix_value ();
00129 
00130               if (error_state)
00131                 return retval;
00132               else
00133                 result = FloatEIG (ftmp_a, nargout > 1);
00134             }
00135           else
00136             {
00137               fctmp_a = arg_a.float_complex_matrix_value ();
00138 
00139               if (error_state)
00140                 return retval;
00141               else
00142                 result = FloatEIG (fctmp_a, nargout > 1);
00143             }
00144         }
00145       else if (nargin == 2)
00146         {
00147           if (arg_a.is_real_type () && arg_b.is_real_type ())
00148             {
00149               ftmp_a = arg_a.float_matrix_value ();
00150               ftmp_b = arg_b.float_matrix_value ();
00151 
00152               if (error_state)
00153                 return retval;
00154               else
00155                 result = FloatEIG (ftmp_a, ftmp_b, nargout > 1);
00156             }
00157           else
00158             {
00159               fctmp_a = arg_a.float_complex_matrix_value ();
00160               fctmp_b = arg_b.float_complex_matrix_value ();
00161 
00162               if (error_state)
00163                 return retval;
00164               else
00165                 result = FloatEIG (fctmp_a, fctmp_b, nargout > 1);
00166             }
00167         }
00168 
00169       if (! error_state)
00170         {
00171           if (nargout == 0 || nargout == 1)
00172             {
00173               retval(0) = result.eigenvalues ();
00174             }
00175           else
00176             {
00177               // Blame it on Matlab.
00178 
00179               FloatComplexDiagMatrix d (result.eigenvalues ());
00180 
00181               retval(1) = d;
00182               retval(0) = result.eigenvectors ();
00183             }
00184         }
00185     }
00186   else
00187     {
00188       EIG result;
00189 
00190       if (nargin == 1)
00191         {
00192           if (arg_a.is_real_type ())
00193             {
00194               tmp_a = arg_a.matrix_value ();
00195 
00196               if (error_state)
00197                 return retval;
00198               else
00199                 result = EIG (tmp_a, nargout > 1);
00200             }
00201           else
00202             {
00203               ctmp_a = arg_a.complex_matrix_value ();
00204 
00205               if (error_state)
00206                 return retval;
00207               else
00208                 result = EIG (ctmp_a, nargout > 1);
00209             }
00210         }
00211       else if (nargin == 2)
00212         {
00213           if (arg_a.is_real_type () && arg_b.is_real_type ())
00214             {
00215               tmp_a = arg_a.matrix_value ();
00216               tmp_b = arg_b.matrix_value ();
00217 
00218               if (error_state)
00219                 return retval;
00220               else
00221                 result = EIG (tmp_a, tmp_b, nargout > 1);
00222             }
00223           else
00224             {
00225               ctmp_a = arg_a.complex_matrix_value ();
00226               ctmp_b = arg_b.complex_matrix_value ();
00227 
00228               if (error_state)
00229                 return retval;
00230               else
00231                 result = EIG (ctmp_a, ctmp_b, nargout > 1);
00232             }
00233         }
00234 
00235       if (! error_state)
00236         {
00237           if (nargout == 0 || nargout == 1)
00238             {
00239               retval(0) = result.eigenvalues ();
00240             }
00241           else
00242             {
00243               // Blame it on Matlab.
00244 
00245               ComplexDiagMatrix d (result.eigenvalues ());
00246 
00247               retval(1) = d;
00248               retval(0) = result.eigenvectors ();
00249             }
00250         }
00251     }
00252 
00253   return retval;
00254 }
00255 
00256 /*
00257 
00258 %!assert(eig ([1, 2; 2, 1]), [-1; 3], sqrt (eps));
00259 
00260 %!test
00261 %! [v, d] = eig ([1, 2; 2, 1]);
00262 %! x = 1 / sqrt (2);
00263 %! assert(d, [-1, 0; 0, 3], sqrt (eps));
00264 %! assert(v, [-x, x; x, x], sqrt (eps));
00265 
00266 %!assert(eig (single ([1, 2; 2, 1])), single([-1; 3]), sqrt (eps('single')));
00267 
00268 %!test
00269 %! [v, d] = eig (single([1, 2; 2, 1]));
00270 %! x = single(1 / sqrt (2));
00271 %! assert(d, single([-1, 0; 0, 3]), sqrt (eps('single')));
00272 %! assert(v, [-x, x; x, x], sqrt (eps('single')));
00273 
00274 %!test
00275 %! A = [1, 2; -1, 1]; B = [3, 3; 1, 2];
00276 %! [v, d] = eig (A, B);
00277 %! assert(A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps));
00278 %! assert(A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps));
00279 
00280 %!test
00281 %! A = single([1, 2; -1, 1]); B = single([3, 3; 1, 2]);
00282 %! [v, d] = eig (A, B);
00283 %! assert(A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps('single')));
00284 %! assert(A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps('single')));
00285 
00286 %!test
00287 %! A = [1, 2; 2, 1]; B = [3, -2; -2, 3];
00288 %! [v, d] = eig (A, B);
00289 %! assert(A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps));
00290 %! assert(A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps));
00291 
00292 %!test
00293 %! A = single([1, 2; 2, 1]); B = single([3, -2; -2, 3]);
00294 %! [v, d] = eig (A, B);
00295 %! assert(A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps('single')));
00296 %! assert(A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps('single')));
00297 
00298 %!test
00299 %! A = [1+3i, 2+i; 2-i, 1+3i]; B = [5+9i, 2+i; 2-i, 5+9i];
00300 %! [v, d] = eig (A, B);
00301 %! assert(A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps));
00302 %! assert(A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps));
00303 
00304 %!test
00305 %! A = single([1+3i, 2+i; 2-i, 1+3i]); B = single([5+9i, 2+i; 2-i, 5+9i]);
00306 %! [v, d] = eig (A, B);
00307 %! assert(A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps('single')));
00308 %! assert(A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps('single')));
00309 
00310 %!test
00311 %! A = [1+3i, 2+3i; 3-8i, 8+3i]; B = [8+i, 3+i; 4-9i, 3+i];
00312 %! [v, d] = eig (A, B);
00313 %! assert(A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps));
00314 %! assert(A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps));
00315 
00316 %!test
00317 %! A = single([1+3i, 2+3i; 3-8i, 8+3i]); B = single([8+i, 3+i; 4-9i, 3+i]);
00318 %! [v, d] = eig (A, B);
00319 %! assert(A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps('single')));
00320 %! assert(A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps('single')));
00321 
00322 %!test
00323 %! A = [1, 2; 3, 8]; B = [8, 3; 4, 3];
00324 %! [v, d] = eig (A, B);
00325 %! assert(A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps));
00326 %! assert(A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps));
00327 
00328 %!error <Invalid call to eig> eig ();
00329 %!error <Invalid call to eig> eig ([1, 2; 3, 4], [4, 3; 2, 1], 1);
00330 %!error eig ([1, 2; 3, 4], 2);
00331 %!error eig ([1, 2; 3, 4; 5, 6]);
00332 %!error eig ("abcd");
00333 %!error eig ([1 2 ; 2 3], "abcd");
00334 %!error eig (false, [1 2 ; 2 3]);
00335 
00336 */
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines