GNU Octave 11.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
ordschur.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 2016-2026 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 "lapack-proto.h"
31
32#include "defun.h"
33#include "error.h"
34#include "ovl.h"
35
37
38DEFUN (ordschur, args, ,
39 doc: /* -*- texinfo -*-
40@deftypefn {} {[@var{UR}, @var{SR}] =} ordschur (@var{U}, @var{S}, @var{select})
41Reorder the real Schur factorization (@var{U},@var{S}) obtained with the
42@code{schur} function, so that selected eigenvalues appear in the upper left
43diagonal blocks of the quasi triangular Schur matrix.
44
45The logical vector @var{select} specifies the selected eigenvalues as they
46appear along @var{S}'s diagonal.
47
48For example, given the matrix @code{@var{A} = [1, 2; 3, 4]}, and its Schur
49decomposition
50
51@example
52[@var{U}, @var{S}] = schur (@var{A})
53@end example
54
55@noindent
56which returns
57
58@example
59@group
60@var{U} =
61
62 -0.82456 -0.56577
63 0.56577 -0.82456
64
65@var{S} =
66
67 -0.37228 -1.00000
68 0.00000 5.37228
69
70@end group
71@end example
72
73It is possible to reorder the decomposition so that the positive eigenvalue
74is in the upper left corner, by doing:
75
76@example
77[@var{U}, @var{S}] = ordschur (@var{U}, @var{S}, [0,1])
78@end example
79
80@seealso{schur, trexc, ordeig, ordqz}
81@end deftypefn */)
82{
83 if (args.length () != 3)
84 print_usage ();
85
86 const Array<octave_idx_type> sel_arg = args(2).xoctave_idx_type_vector_value ("ordschur: SELECT must be an array of integers");
87
88 const octave_idx_type sel_n = sel_arg.numel ();
89
90 const dim_vector dimU = args(0).dims ();
91 const dim_vector dimS = args(1).dims ();
92
93 if (sel_n != dimU(0))
94 error ("ordschur: SELECT must have same length as the sides of U and S");
95 else if (sel_n != dimU(0) || sel_n != dimS(0) || sel_n != dimU(1)
96 || sel_n != dimS(1))
97 error ("ordschur: U and S must be square and of equal sizes");
98
99 octave_value_list retval;
100
101 const bool double_type = args(0).is_double_type () || args(1).is_double_type ();
102 const bool complex_type = args(0).iscomplex () || args(1).iscomplex ();
103
104#define PREPARE_ARGS(TYPE, TYPE_M, TYPE_COND) \
105 TYPE ## Matrix U = args(0).x ## TYPE_M ## _value \
106 ("ordschur: U and S must be real or complex floating point matrices"); \
107 TYPE ## Matrix S = args(1).x ## TYPE_M ## _value \
108 ("ordschur: U and S must be real or complex floating point matrices"); \
109 TYPE ## Matrix w (dim_vector (n, 1)); \
110 TYPE ## Matrix work (dim_vector (n, 1)); \
111 F77_INT m; \
112 F77_INT info; \
113 TYPE_COND cond1, cond2;
114
115#define PREPARE_OUTPUT() \
116 if (info != 0) \
117 error ("ordschur: trsen failed"); \
118 \
119 retval = ovl (U, S);
120
121 F77_INT n = to_f77_int (sel_n);
122 Array<F77_INT> sel (dim_vector (n, 1));
123 for (F77_INT i = 0; i < n; i++)
124 sel.xelem (i) = to_f77_int (sel_arg.xelem (i));
125
126 if (double_type)
127 {
128 if (complex_type)
129 {
130 PREPARE_ARGS (Complex, complex_matrix, double)
131
132 F77_XFCN (ztrsen, ztrsen,
133 (F77_CONST_CHAR_ARG ("N"), F77_CONST_CHAR_ARG ("V"),
134 sel.data (), n, F77_DBLE_CMPLX_ARG (S.rwdata ()), n,
135 F77_DBLE_CMPLX_ARG (U.rwdata ()), n,
136 F77_DBLE_CMPLX_ARG (w.rwdata ()), m, cond1, cond2,
137 F77_DBLE_CMPLX_ARG (work.rwdata ()), n, info
138 F77_CHAR_ARG_LEN (1) F77_CHAR_ARG_LEN (1)));
139
141 }
142 else
143 {
144 PREPARE_ARGS (, matrix, double)
145 Matrix wi (dim_vector (n, 1));
146 Array<F77_INT> iwork (dim_vector (n, 1));
147
148 F77_XFCN (dtrsen, dtrsen,
149 (F77_CONST_CHAR_ARG ("N"), F77_CONST_CHAR_ARG ("V"),
150 sel.data (), n, S.rwdata (), n, U.rwdata (), n,
151 w.rwdata (), wi.rwdata (), m, cond1, cond2,
152 work.rwdata (), n, iwork.rwdata (), n, info
153 F77_CHAR_ARG_LEN (1) F77_CHAR_ARG_LEN (1)));
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.rwdata ()), n,
167 F77_CMPLX_ARG (U.rwdata ()), n,
168 F77_CMPLX_ARG (w.rwdata ()), m, cond1, cond2,
169 F77_CMPLX_ARG (work.rwdata ()), n, info
170 F77_CHAR_ARG_LEN (1) F77_CHAR_ARG_LEN (1)));
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.rwdata (), n, U.rwdata (), n,
183 w.rwdata (), wi.rwdata (), m, cond1, cond2,
184 work.rwdata (), n, iwork.rwdata (), n, info
185 F77_CHAR_ARG_LEN (1) F77_CHAR_ARG_LEN (1)));
186
188 }
189 }
190
191#undef PREPARE_ARGS
192#undef PREPARE_OUTPUT
193
194 return retval;
195}
196
197/*
198
199%!test
200%! A = [1, 2, 3, -2; 4, 5, 6, -5 ; 7, 8, 9, -5; 10, 11, 12, 4 ];
201%! [U, T] = schur (A);
202%! [US, TS] = ordschur (U, T, [ 0, 0, 1, 1 ]);
203%! assert (US*TS*US', A, sqrt (eps));
204%! assert (diag (T)(3:4), diag (TS)(1:2), sqrt (eps));
205
206%!test
207%! A = [1, 2, 3, -2; 4, 5, 6, -5 ; 7, 8, 9, -5; 10, 11, 12, 4 ];
208%! [U, T] = schur (A);
209%! [US, TS] = ordschur (single (U), single (T), [ 0, 0, 1, 1 ]);
210%! assert (US*TS*US', A, sqrt (eps ("single")));
211%! assert (diag (T)(3:4), diag (TS)(1:2), sqrt (eps ("single")));
212
213%!test
214%! A = [1, 2, 3, -2; 4, 5, 6, -5 ; 7, 8, 9, -5; 10, 11, 12, 4+3i ];
215%! [U, T] = schur (A);
216%! [US, TS] = ordschur (U, T, [ 0, 0, 1, 1 ]);
217%! assert (US*TS*US', A, sqrt (eps));
218%! assert (diag (T)(3:4), diag (TS)(1:2), sqrt (eps));
219
220%!test
221%! A = [1, 2, 3, -2; 4, 5, 6, -5 ; 7, 8, 9, -5; 10, 11, 12, 4+3i ];
222%! [U, T] = schur (A);
223%! [US, TS] = ordschur (single (U), single (T), [ 0, 0, 1, 1 ]);
224%! assert (US*TS*US', A, sqrt (eps ("single")));
225%! assert (diag (T)(3:4), diag (TS)(1:2), sqrt (eps ("single")));
226
227*/
228
229OCTAVE_END_NAMESPACE(octave)
N Dimensional Array with copy-on-write semantics.
Definition Array-base.h:130
T & xelem(octave_idx_type n)
Size of the specified dimension.
Definition Array-base.h:547
const T * data() const
Size of the specified dimension.
Definition Array-base.h:687
T * rwdata()
Size of the specified dimension.
octave_idx_type numel() const
Number of elements in the array.
Definition Array-base.h:440
Vector representing the dimensions (size) of an Array.
Definition dim-vector.h:92
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void print_usage()
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:1008
#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 > 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)