Advertisement
BumiBarbi

eig.cc

Mar 29th, 2016
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.00 KB | None | 0 0
  1. /*
  2.  
  3. Copyright (C) 1996-2015 John W. Eaton
  4.  
  5. This file is part of Octave.
  6.  
  7. Octave is free software; you can redistribute it and/or modify it
  8. under the terms of the GNU General Public License as published by the
  9. Free Software Foundation; either version 3 of the License, or (at your
  10. option) any later version.
  11.  
  12. Octave is distributed in the hope that it will be useful, but WITHOUT
  13. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with Octave; see the file COPYING.  If not, see
  19. <http://www.gnu.org/licenses/>.
  20.  
  21. */
  22.  
  23. #ifdef HAVE_CONFIG_H
  24. #  include "config.h"
  25. #endif
  26.  
  27. #include "EIG.h"
  28. #include "fEIG.h"
  29.  
  30. #include "defun.h"
  31. #include "error.h"
  32. #include "errwarn.h"
  33. #include "ovl.h"
  34. #include "utils.h"
  35.  
  36. DEFUN (eig, args, nargout,
  37.        "-*- texinfo -*-\n\
  38. @deftypefn  {} {@var{lambda} =} eig (@var{A})\n\
  39. @deftypefnx {} {@var{lambda} =} eig (@var{A}, @var{B})\n\
  40. @deftypefnx {} {[@var{V}, @var{lambda}] =} eig (@var{A})\n\
  41. @deftypefnx {} {[@var{V}, @var{lambda}] =} eig (@var{A}, @var{B})\n\
  42. Compute the eigenvalues (and optionally the eigenvectors) of a matrix\n\
  43. or a pair of matrices\n\
  44. \n\
  45. The algorithm used depends on whether there are one or two input\n\
  46. matrices, if they are real or complex, and if they are symmetric\n\
  47. (Hermitian if complex) or non-symmetric.\n\
  48. \n\
  49. The eigenvalues returned by @code{eig} are not ordered.\n\
  50. @seealso{eigs, svd}\n\
  51. @end deftypefn")
  52. {
  53.   int nargin = args.length ();
  54.  
  55.   if (nargin > 2 || nargin == 0)
  56.     print_usage ();
  57.  
  58.   octave_value_list retval;
  59.  
  60.   octave_value arg_a, arg_b;
  61.  
  62.   octave_idx_type nr_a, nr_b, nc_a, nc_b;
  63.   nr_a = nr_b = nc_a = nc_b = 0;
  64.  
  65.   arg_a = args(0);
  66.   nr_a = arg_a.rows ();
  67.   nc_a = arg_a.columns ();
  68.  
  69.   int arg_is_empty = empty_arg ("eig", nr_a, nc_a);
  70.   if (arg_is_empty < 0)
  71.     return retval;
  72.   else if (arg_is_empty > 0)
  73.     return octave_value_list (2, Matrix ());
  74.  
  75.   if (! arg_a.is_double_type () && ! arg_a.is_single_type ())
  76.     err_wrong_type_arg ("eig", arg_a);
  77.  
  78.   bool balance = true;
  79.   if (nargin == 2)
  80.     {
  81.       if(args(1).is_string ())
  82.         {
  83.           std::string a1s = args(1).string_value ();
  84.           if(a1s != "balance" && a1s != "nobalance")
  85.             error ("eig: unexpected second input: %s", a1s.c_str ());
  86.           balance = a1s == "balance";
  87.         }
  88.       else
  89.         {
  90.           arg_b = args(1);
  91.           nr_b = arg_b.rows ();
  92.           nc_b = arg_b.columns ();
  93.  
  94.           arg_is_empty = empty_arg ("eig", nr_b, nc_b);
  95.           if (arg_is_empty < 0)
  96.             return retval;
  97.           else if (arg_is_empty > 0)
  98.             return ovl (2, Matrix ());
  99.  
  100.           if (! arg_b.is_single_type () && ! arg_b.is_double_type ())
  101.             err_wrong_type_arg ("eig", arg_b);
  102.         }
  103.     }
  104.  
  105.   if (nr_a != nc_a)
  106.     err_square_matrix_required ("eig", "A");
  107.  
  108.   // determine if it's AEP or GEP
  109.   bool AEPcase = nargin == 1 || args(1).is_string ();
  110.  
  111.   if (!AEPcase && nr_b != nc_b)
  112.     err_square_matrix_required ("eig", "B");
  113.  
  114.   Matrix tmp_a, tmp_b;
  115.   ComplexMatrix ctmp_a, ctmp_b;
  116.   FloatMatrix ftmp_a, ftmp_b;
  117.   FloatComplexMatrix fctmp_a, fctmp_b;
  118.  
  119.   if (arg_a.is_single_type ())
  120.     {
  121.       FloatEIG result;
  122.  
  123.       if (AEPcase)
  124.         {
  125.           if (arg_a.is_real_type ())
  126.             {
  127.               ftmp_a = arg_a.float_matrix_value ();
  128.  
  129.               result = FloatEIG (ftmp_a, nargout > 1, balance);
  130.             }
  131.           else
  132.             {
  133.               fctmp_a = arg_a.float_complex_matrix_value ();
  134.  
  135.               result = FloatEIG (fctmp_a, nargout > 1, balance);
  136.             }
  137.         }
  138.       else
  139.         {
  140.           if (arg_a.is_real_type () && arg_b.is_real_type ())
  141.             {
  142.               ftmp_a = arg_a.float_matrix_value ();
  143.               ftmp_b = arg_b.float_matrix_value ();
  144.  
  145.               result = FloatEIG (ftmp_a, ftmp_b, nargout > 1);
  146.             }
  147.           else
  148.             {
  149.               fctmp_a = arg_a.float_complex_matrix_value ();
  150.               fctmp_b = arg_b.float_complex_matrix_value ();
  151.  
  152.               result = FloatEIG (fctmp_a, fctmp_b, nargout > 1);
  153.             }
  154.         }
  155.  
  156.       if (nargout == 0 || nargout == 1)
  157.         {
  158.           retval = ovl (result.eigenvalues ());
  159.         }
  160.       else
  161.         {
  162.           // Blame it on Matlab.
  163.           FloatComplexDiagMatrix d (result.eigenvalues ());
  164.  
  165.           retval = ovl (result.eigenvectors (), d);
  166.         }
  167.     }
  168.   else
  169.     {
  170.       EIG result;
  171.  
  172.       if (AEPcase)
  173.         {
  174.           if (arg_a.is_real_type ())
  175.             {
  176.               tmp_a = arg_a.matrix_value ();
  177.  
  178.               result = EIG (tmp_a, nargout > 1, balance);
  179.             }
  180.           else
  181.             {
  182.               ctmp_a = arg_a.complex_matrix_value ();
  183.  
  184.               result = EIG (ctmp_a, nargout > 1, balance);
  185.             }
  186.         }
  187.       else
  188.         {
  189.           if (arg_a.is_real_type () && arg_b.is_real_type ())
  190.             {
  191.               tmp_a = arg_a.matrix_value ();
  192.               tmp_b = arg_b.matrix_value ();
  193.  
  194.               result = EIG (tmp_a, tmp_b, nargout > 1);
  195.             }
  196.           else
  197.             {
  198.               ctmp_a = arg_a.complex_matrix_value ();
  199.               ctmp_b = arg_b.complex_matrix_value ();
  200.  
  201.               result = EIG (ctmp_a, ctmp_b, nargout > 1);
  202.             }
  203.         }
  204.  
  205.       if (nargout == 0 || nargout == 1)
  206.         {
  207.           retval = ovl (result.eigenvalues ());
  208.         }
  209.       else
  210.         {
  211.           // Blame it on Matlab.
  212.           ComplexDiagMatrix d (result.eigenvalues ());
  213.  
  214.           retval = ovl (result.eigenvectors (), d);
  215.         }
  216.     }
  217.  
  218.   return retval;
  219. }
  220.  
  221. /*
  222. %!assert (eig ([1, 2; 2, 1]), [-1; 3], sqrt (eps))
  223.  
  224. %!test
  225. %! [v, d] = eig ([1, 2; 2, 1]);
  226. %! x = 1 / sqrt (2);
  227. %! assert (d, [-1, 0; 0, 3], sqrt (eps));
  228. %! assert (v, [-x, x; x, x], sqrt (eps));
  229.  
  230. %!assert (eig (single ([1, 2; 2, 1])), single ([-1; 3]), sqrt (eps ("single")))
  231.  
  232. %!test
  233. %! [v, d] = eig (single ([1, 2; 2, 1]));
  234. %! x = single (1 / sqrt (2));
  235. %! assert (d, single ([-1, 0; 0, 3]), sqrt (eps ("single")));
  236. %! assert (v, [-x, x; x, x], sqrt (eps ("single")));
  237.  
  238. %!test
  239. %! A = [1, 2; -1, 1];  B = [3, 3; 1, 2];
  240. %! [v, d] = eig (A, B);
  241. %! assert (A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps));
  242. %! assert (A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps));
  243.  
  244. %!test
  245. %! A = single ([1, 2; -1, 1]);  B = single ([3, 3; 1, 2]);
  246. %! [v, d] = eig (A, B);
  247. %! assert (A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps ("single")));
  248. %! assert (A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps ("single")));
  249.  
  250. %!test
  251. %! A = [1, 2; 2, 1];  B = [3, -2; -2, 3];
  252. %! [v, d] = eig (A, B);
  253. %! assert (A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps));
  254. %! assert (A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps));
  255.  
  256. %!test
  257. %! A = single ([1, 2; 2, 1]);  B = single ([3, -2; -2, 3]);
  258. %! [v, d] = eig (A, B);
  259. %! assert (A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps ("single")));
  260. %! assert (A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps ("single")));
  261.  
  262. %!test
  263. %! A = [1+3i, 2+i; 2-i, 1+3i];  B = [5+9i, 2+i; 2-i, 5+9i];
  264. %! [v, d] = eig (A, B);
  265. %! assert (A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps));
  266. %! assert (A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps));
  267.  
  268. %!test
  269. %! A = single ([1+3i, 2+i; 2-i, 1+3i]);  B = single ([5+9i, 2+i; 2-i, 5+9i]);
  270. %! [v, d] = eig (A, B);
  271. %! assert (A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps ("single")));
  272. %! assert (A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps ("single")));
  273.  
  274. %!test
  275. %! A = [1+3i, 2+3i; 3-8i, 8+3i];  B = [8+i, 3+i; 4-9i, 3+i];
  276. %! [v, d] = eig (A, B);
  277. %! assert (A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps));
  278. %! assert (A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps));
  279.  
  280. %!test
  281. %! A = single ([1+3i, 2+3i; 3-8i, 8+3i]);  B = single ([8+i, 3+i; 4-9i, 3+i]);
  282. %! [v, d] = eig (A, B);
  283. %! assert (A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps ("single")));
  284. %! assert (A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps ("single")));
  285.  
  286. %!test
  287. %! A = [1, 2; 3, 8];  B = [8, 3; 4, 3];
  288. %! [v, d] = eig (A, B);
  289. %! assert (A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps));
  290. %! assert (A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps));
  291.  
  292. %!test
  293. %! A = [1, 1+i; 1-i, 1];  B = [2, 0; 0, 2];
  294. %! [v, d] = eig (A, B);
  295. %! assert (A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps));
  296. %! assert (A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps));
  297.  
  298. %!test
  299. %! A = single ([1, 1+i; 1-i, 1]);  B = single ([2, 0; 0, 2]);
  300. %! [v, d] = eig (A, B);
  301. %! assert (A * v(:, 1), d(1, 1) * B * v(:, 1), sqrt (eps ("single")));
  302. %! assert (A * v(:, 2), d(2, 2) * B * v(:, 2), sqrt (eps ("single")));
  303.  
  304. %!error eig ()
  305. %!error eig ([1, 2; 3, 4], [4, 3; 2, 1], 1)
  306. %!error <EIG requires same size matrices> eig ([1, 2; 3, 4], 2)
  307. %!error <must be a square matrix> eig ([1, 2; 3, 4; 5, 6])
  308. %!error <wrong type argument> eig ("abcd")
  309. %!error <wrong type argument> eig ([1 2 ; 2 3], "abcd")
  310. %!error <wrong type argument> eig (false, [1 2 ; 2 3])
  311. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement