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