GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
ordschur.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2016-2018 Sébastien Villemot <sebastien@debian.org>
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
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License 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 <https://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include "defun.h"
28 #include "error.h"
29 #include "lo-lapack-proto.h"
30 #include "ovl.h"
31 
32 DEFUN (ordschur, args, ,
33  doc: /* -*- texinfo -*-
34 @deftypefn {} {[@var{UR}, @var{SR}] =} ordschur (@var{U}, @var{S}, @var{select})
35 Reorders the real Schur factorization (@var{U},@var{S}) obtained with the
36 @code{schur} function, so that selected eigenvalues appear in the upper left
37 diagonal blocks of the quasi triangular Schur matrix.
38 
39 The logical vector @var{select} specifies the selected eigenvalues as they
40 appear along @var{S}'s diagonal.
41 
42 For example, given the matrix @code{@var{A} = [1, 2; 3, 4]}, and its Schur
43 decomposition
44 
45 @example
46 [@var{U}, @var{S}] = schur (@var{A})
47 @end example
48 
49 @noindent
50 which returns
51 
52 @example
53 @group
54 @var{U} =
55 
56  -0.82456 -0.56577
57  0.56577 -0.82456
58 
59 @var{S} =
60 
61  -0.37228 -1.00000
62  0.00000 5.37228
63 
64 @end group
65 @end example
66 
67 It is possible to reorder the decomposition so that the positive eigenvalue
68 is in the upper left corner, by doing:
69 
70 @example
71 [@var{U}, @var{S}] = ordschur (@var{U}, @var{S}, [0,1])
72 @end example
73 
74 @seealso{schur}
75 @end deftypefn */)
76 {
77  if (args.length () != 3)
78  print_usage ();
79 
80  const Array<octave_idx_type> sel_arg = args(2).octave_idx_type_vector_value ("ordschur: SELECT must be an array of integers");
81 
82  const octave_idx_type sel_n = sel_arg.numel ();
83 
84  const dim_vector dimU = args(0).dims ();
85  const dim_vector dimS = args(1).dims ();
86 
87  if (sel_n != dimU(0))
88  error ("ordschur: SELECT must have same length as the sides of U and S");
89  else if (sel_n != dimU(0) || sel_n != dimS(0) || sel_n != dimU(1)
90  || sel_n != dimS(1))
91  error ("ordschur: U and S must be square and of equal sizes");
92 
94 
95  const bool double_type = args(0).is_double_type ()
96  || args(1).is_double_type ();
97  const bool complex_type = args(0).iscomplex ()
98  || args(1).iscomplex ();
99 
100 #define PREPARE_ARGS(TYPE, TYPE_M, TYPE_COND) \
101  TYPE ## Matrix U = args(0).x ## TYPE_M ## _value \
102  ("ordschur: U and S must be real or complex floating point matrices"); \
103  TYPE ## Matrix S = args(1).x ## TYPE_M ## _value \
104  ("ordschur: U and S must be real or complex floating point matrices"); \
105  TYPE ## Matrix w (dim_vector (n, 1)); \
106  TYPE ## Matrix work (dim_vector (n, 1)); \
107  F77_INT m; \
108  F77_INT info; \
109  TYPE_COND cond1, cond2;
110 
111 #define PREPARE_OUTPUT() \
112  if (info != 0) \
113  error ("ordschur: trsen failed"); \
114  \
115  retval = ovl (U, S);
116 
117  F77_INT n = octave::to_f77_int (sel_n);
118  Array<F77_INT> sel (dim_vector (n, 1));
119  for (F77_INT i = 0; i < n; i++)
120  sel.xelem (i) = octave::to_f77_int (sel_arg.xelem (i));
121 
122  if (double_type)
123  {
124  if (complex_type)
125  {
126  PREPARE_ARGS (Complex, complex_matrix, double)
127 
128  F77_XFCN (ztrsen, ztrsen,
129  (F77_CONST_CHAR_ARG ("N"), F77_CONST_CHAR_ARG ("V"),
130  sel.data (), n, F77_DBLE_CMPLX_ARG (S.fortran_vec ()), n,
131  F77_DBLE_CMPLX_ARG (U.fortran_vec ()), n,
132  F77_DBLE_CMPLX_ARG (w.fortran_vec ()), m, cond1, cond2,
133  F77_DBLE_CMPLX_ARG (work.fortran_vec ()), n,
134  info));
135 
137  }
138  else
139  {
140  PREPARE_ARGS (, matrix, double)
141  Matrix wi (dim_vector (n, 1));
142  Array<F77_INT> iwork (dim_vector (n, 1));
143 
144  F77_XFCN (dtrsen, dtrsen,
145  (F77_CONST_CHAR_ARG ("N"), F77_CONST_CHAR_ARG ("V"),
146  sel.data (), n, S.fortran_vec (), n, U.fortran_vec (), n,
147  w.fortran_vec (), wi.fortran_vec (), m, cond1, cond2,
148  work.fortran_vec (), n, iwork.fortran_vec (), n, info));
149 
150  PREPARE_OUTPUT ()
151  }
152  }
153  else
154  {
155  if (complex_type)
156  {
157  PREPARE_ARGS (FloatComplex, float_complex_matrix, float)
158 
159  F77_XFCN (ctrsen, ctrsen,
160  (F77_CONST_CHAR_ARG ("N"), F77_CONST_CHAR_ARG ("V"),
161  sel.data (), n, F77_CMPLX_ARG (S.fortran_vec ()), n,
162  F77_CMPLX_ARG (U.fortran_vec ()), n,
163  F77_CMPLX_ARG (w.fortran_vec ()), m, cond1, cond2,
164  F77_CMPLX_ARG (work.fortran_vec ()), n,
165  info));
166 
167  PREPARE_OUTPUT ()
168  }
169  else
170  {
171  PREPARE_ARGS (Float, float_matrix, float)
172  FloatMatrix wi (dim_vector (n, 1));
173  Array<F77_INT> iwork (dim_vector (n, 1));
174 
175  F77_XFCN (strsen, strsen,
176  (F77_CONST_CHAR_ARG ("N"), F77_CONST_CHAR_ARG ("V"),
177  sel.data (), n, S.fortran_vec (), n, U.fortran_vec (), n,
178  w.fortran_vec (), wi.fortran_vec (), m, cond1, cond2,
179  work.fortran_vec (), n, iwork.fortran_vec (), n, info));
180 
181  PREPARE_OUTPUT ()
182  }
183  }
184 
185 #undef PREPARE_ARGS
186 #undef PREPARE_OUTPUT
187 
188  return retval;
189 }
190 
191 /*
192 
193 %!test
194 %! A = [1, 2, 3, -2; 4, 5, 6, -5 ; 7, 8, 9, -5; 10, 11, 12, 4 ];
195 %! [U, T] = schur (A);
196 %! [US, TS] = ordschur (U, T, [ 0, 0, 1, 1 ]);
197 %! assert (US*TS*US', A, sqrt (eps));
198 %! assert (diag (T)(3:4), diag (TS)(1:2), sqrt (eps));
199 
200 %!test
201 %! A = [1, 2, 3, -2; 4, 5, 6, -5 ; 7, 8, 9, -5; 10, 11, 12, 4 ];
202 %! [U, T] = schur (A);
203 %! [US, TS] = ordschur (single (U), single (T), [ 0, 0, 1, 1 ]);
204 %! assert (US*TS*US', A, sqrt (eps ("single")));
205 %! assert (diag (T)(3:4), diag (TS)(1:2), sqrt (eps ("single")));
206 
207 %!test
208 %! A = [1, 2, 3, -2; 4, 5, 6, -5 ; 7, 8, 9, -5; 10, 11, 12, 4+3i ];
209 %! [U, T] = schur (A);
210 %! [US, TS] = ordschur (U, T, [ 0, 0, 1, 1 ]);
211 %! assert (US*TS*US', A, sqrt (eps));
212 %! assert (diag (T)(3:4), diag (TS)(1:2), sqrt (eps));
213 
214 %!test
215 %! A = [1, 2, 3, -2; 4, 5, 6, -5 ; 7, 8, 9, -5; 10, 11, 12, 4+3i ];
216 %! [U, T] = schur (A);
217 %! [US, TS] = ordschur (single (U), single (T), [ 0, 0, 1, 1 ]);
218 %! assert (US*TS*US', A, sqrt (eps ("single")));
219 %! assert (diag (T)(3:4), diag (TS)(1:2), sqrt (eps ("single")));
220 
221 */
#define PREPARE_ARGS(TYPE, TYPE_M, TYPE_COND)
characters Given a string matrix
Definition: hex2num.cc:155
const T * data(void) const
Definition: Array.h:582
OCTINTERP_API void print_usage(void)
Definition: defun.cc:54
#define F77_DBLE_CMPLX_ARG(x)
Definition: f77-fcn.h:315
const T * fortran_vec(void) const
Definition: Array.h:584
#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
#define F77_XFCN(f, F, args)
Definition: f77-fcn.h:41
#define PREPARE_OUTPUT()
std::complex< double > w(std::complex< double > z, double relerr=0)
octave_value retval
Definition: data.cc:6246
Definition: dMatrix.h:36
T & xelem(octave_idx_type n)
Definition: Array.h:458
#define F77_CMPLX_ARG(x)
Definition: f77-fcn.h:309
octave_f77_int_type F77_INT
Definition: f77-fcn.h:305
static double wi[256]
Definition: randmtzig.cc:435
for i
Definition: data.cc:5264
std::complex< float > FloatComplex
Definition: oct-cmplx.h:32
bool is_double_type(void) const
Definition: ov.h:648
std::complex< double > Complex
Definition: oct-cmplx.h:31
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:366
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87