GNU Octave 10.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-2025 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
36
37DEFUN (ordschur, args, ,
38 doc: /* -*- texinfo -*-
39@deftypefn {} {[@var{UR}, @var{SR}] =} ordschur (@var{U}, @var{S}, @var{select})
40Reorder 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 () || args(1).is_double_type ();
101 const bool complex_type = args(0).iscomplex () || args(1).iscomplex ();
102
103#define PREPARE_ARGS(TYPE, TYPE_M, TYPE_COND) \
104 TYPE ## Matrix U = args(0).x ## TYPE_M ## _value \
105 ("ordschur: U and S must be real or complex floating point matrices"); \
106 TYPE ## Matrix S = args(1).x ## TYPE_M ## _value \
107 ("ordschur: U and S must be real or complex floating point matrices"); \
108 TYPE ## Matrix w (dim_vector (n, 1)); \
109 TYPE ## Matrix work (dim_vector (n, 1)); \
110 F77_INT m; \
111 F77_INT info; \
112 TYPE_COND cond1, cond2;
113
114#define PREPARE_OUTPUT() \
115 if (info != 0) \
116 error ("ordschur: trsen failed"); \
117 \
118 retval = ovl (U, S);
119
120 F77_INT n = to_f77_int (sel_n);
121 Array<F77_INT> sel (dim_vector (n, 1));
122 for (F77_INT i = 0; i < n; i++)
123 sel.xelem (i) = to_f77_int (sel_arg.xelem (i));
124
125 if (double_type)
126 {
127 if (complex_type)
128 {
129 PREPARE_ARGS (Complex, complex_matrix, double)
130
131 F77_XFCN (ztrsen, ztrsen,
132 (F77_CONST_CHAR_ARG ("N"), F77_CONST_CHAR_ARG ("V"),
133 sel.data (), n, F77_DBLE_CMPLX_ARG (S.rwdata ()), n,
134 F77_DBLE_CMPLX_ARG (U.rwdata ()), n,
135 F77_DBLE_CMPLX_ARG (w.rwdata ()), m, cond1, cond2,
136 F77_DBLE_CMPLX_ARG (work.rwdata ()), n,
137 info));
138
140 }
141 else
142 {
143 PREPARE_ARGS (, matrix, double)
144 Matrix wi (dim_vector (n, 1));
145 Array<F77_INT> iwork (dim_vector (n, 1));
146
147 F77_XFCN (dtrsen, dtrsen,
148 (F77_CONST_CHAR_ARG ("N"), F77_CONST_CHAR_ARG ("V"),
149 sel.data (), n, S.rwdata (), n, U.rwdata (), n,
150 w.rwdata (), wi.rwdata (), m, cond1, cond2,
151 work.rwdata (), n, iwork.rwdata (), n, info));
152
154 }
155 }
156 else
157 {
158 if (complex_type)
159 {
160 PREPARE_ARGS (FloatComplex, float_complex_matrix, float)
161
162 F77_XFCN (ctrsen, ctrsen,
163 (F77_CONST_CHAR_ARG ("N"), F77_CONST_CHAR_ARG ("V"),
164 sel.data (), n, F77_CMPLX_ARG (S.rwdata ()), n,
165 F77_CMPLX_ARG (U.rwdata ()), n,
166 F77_CMPLX_ARG (w.rwdata ()), m, cond1, cond2,
167 F77_CMPLX_ARG (work.rwdata ()), n,
168 info));
169
171 }
172 else
173 {
174 PREPARE_ARGS (Float, float_matrix, float)
175 FloatMatrix wi (dim_vector (n, 1));
176 Array<F77_INT> iwork (dim_vector (n, 1));
177
178 F77_XFCN (strsen, strsen,
179 (F77_CONST_CHAR_ARG ("N"), F77_CONST_CHAR_ARG ("V"),
180 sel.data (), n, S.rwdata (), n, U.rwdata (), n,
181 w.rwdata (), wi.rwdata (), m, cond1, cond2,
182 work.rwdata (), n, iwork.rwdata (), n, info));
183
185 }
186 }
187
188#undef PREPARE_ARGS
189#undef PREPARE_OUTPUT
190
191 return retval;
192}
193
194/*
195
196%!test
197%! A = [1, 2, 3, -2; 4, 5, 6, -5 ; 7, 8, 9, -5; 10, 11, 12, 4 ];
198%! [U, T] = schur (A);
199%! [US, TS] = ordschur (U, T, [ 0, 0, 1, 1 ]);
200%! assert (US*TS*US', A, sqrt (eps));
201%! assert (diag (T)(3:4), diag (TS)(1:2), sqrt (eps));
202
203%!test
204%! A = [1, 2, 3, -2; 4, 5, 6, -5 ; 7, 8, 9, -5; 10, 11, 12, 4 ];
205%! [U, T] = schur (A);
206%! [US, TS] = ordschur (single (U), single (T), [ 0, 0, 1, 1 ]);
207%! assert (US*TS*US', A, sqrt (eps ("single")));
208%! assert (diag (T)(3:4), diag (TS)(1:2), sqrt (eps ("single")));
209
210%!test
211%! A = [1, 2, 3, -2; 4, 5, 6, -5 ; 7, 8, 9, -5; 10, 11, 12, 4+3i ];
212%! [U, T] = schur (A);
213%! [US, TS] = ordschur (U, T, [ 0, 0, 1, 1 ]);
214%! assert (US*TS*US', A, sqrt (eps));
215%! assert (diag (T)(3:4), diag (TS)(1:2), sqrt (eps));
216
217%!test
218%! A = [1, 2, 3, -2; 4, 5, 6, -5 ; 7, 8, 9, -5; 10, 11, 12, 4+3i ];
219%! [U, T] = schur (A);
220%! [US, TS] = ordschur (single (U), single (T), [ 0, 0, 1, 1 ]);
221%! assert (US*TS*US', A, sqrt (eps ("single")));
222%! assert (diag (T)(3:4), diag (TS)(1:2), sqrt (eps ("single")));
223
224*/
225
226OCTAVE_END_NAMESPACE(octave)
N Dimensional Array with copy-on-write semantics.
Definition Array.h:130
T & xelem(octave_idx_type n)
Size of the specified dimension.
Definition Array.h:525
const T * data() const
Size of the specified dimension.
Definition Array.h:665
T * rwdata()
Size of the specified dimension.
octave_idx_type numel() const
Number of elements in the array.
Definition Array.h:418
Vector representing the dimensions (size) of an Array.
Definition dim-vector.h:90
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:1003
#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)