GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
schur.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1994-2017 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 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include "CMatrix.h"
28 #include "dMatrix.h"
29 #include "fCMatrix.h"
30 #include "fMatrix.h"
31 #include "lo-error.h"
32 #include "lo-lapack-proto.h"
33 #include "schur.h"
34 
35 namespace octave
36 {
37  namespace math
38  {
39  // For real types.
40 
41  template <typename T>
42  static octave_idx_type
43  select_ana (const T& a, const T&)
44  {
45  return (a < 0.0);
46  }
47 
48  template <typename T>
49  static octave_idx_type
50  select_dig (const T& a, const T& b)
51  {
52  return (hypot (a, b) < 1.0);
53  }
54 
55  // For complex types.
56 
57  template <typename T>
58  static octave_idx_type
59  select_ana (const T& a)
60  {
61  return a.real () < 0.0;
62  }
63 
64  template <typename T>
65  static octave_idx_type
66  select_dig (const T& a)
67  {
68  return (abs (a) < 1.0);
69  }
70 
71  template <>
73  schur<Matrix>::init (const Matrix& a, const std::string& ord, bool calc_unitary)
74  {
75  octave_idx_type a_nr = a.rows ();
76  octave_idx_type a_nc = a.cols ();
77 
78  if (a_nr != a_nc)
79  (*current_liboctave_error_handler) ("schur: requires square matrix");
80 
81  if (a_nr == 0)
82  {
83  schur_mat.clear ();
84  unitary_mat.clear ();
85  return 0;
86  }
87 
88  // Workspace requirements may need to be fixed if any of the
89  // following change.
90 
91  char jobvs;
92  char sense = 'N';
93  char sort = 'N';
94 
95  if (calc_unitary)
96  jobvs = 'V';
97  else
98  jobvs = 'N';
99 
100  char ord_char = ord.empty () ? 'U' : ord[0];
101 
102  if (ord_char == 'A' || ord_char == 'D' || ord_char == 'a' || ord_char == 'd')
103  sort = 'S';
104 
105  volatile double_selector selector = 0;
106  if (ord_char == 'A' || ord_char == 'a')
107  selector = select_ana<double>;
108  else if (ord_char == 'D' || ord_char == 'd')
109  selector = select_dig<double>;
110 
111  octave_idx_type n = a_nc;
112  octave_idx_type lwork = 8 * n;
113  octave_idx_type liwork = 1;
114  octave_idx_type info;
115  octave_idx_type sdim;
116  double rconde;
117  double rcondv;
118 
119  schur_mat = a;
120 
121  if (calc_unitary)
122  unitary_mat.clear (n, n);
123 
124  double *s = schur_mat.fortran_vec ();
125  double *q = unitary_mat.fortran_vec ();
126 
127  Array<double> wr (dim_vector (n, 1));
128  double *pwr = wr.fortran_vec ();
129 
130  Array<double> wi (dim_vector (n, 1));
131  double *pwi = wi.fortran_vec ();
132 
133  Array<double> work (dim_vector (lwork, 1));
134  double *pwork = work.fortran_vec ();
135 
136  // BWORK is not referenced for the non-ordered Schur routine.
137  octave_idx_type ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n;
138  Array<octave_idx_type> bwork (dim_vector (ntmp, 1));
139  octave_idx_type *pbwork = bwork.fortran_vec ();
140 
141  Array<octave_idx_type> iwork (dim_vector (liwork, 1));
142  octave_idx_type *piwork = iwork.fortran_vec ();
143 
144  F77_XFCN (dgeesx, DGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1),
145  F77_CONST_CHAR_ARG2 (&sort, 1),
146  selector,
147  F77_CONST_CHAR_ARG2 (&sense, 1),
148  n, s, n, sdim, pwr, pwi, q, n, rconde, rcondv,
149  pwork, lwork, piwork, liwork, pbwork, info
150  F77_CHAR_ARG_LEN (1)
151  F77_CHAR_ARG_LEN (1)
152  F77_CHAR_ARG_LEN (1)));
153 
154  return info;
155  }
156 
157  template <>
160  bool calc_unitary)
161  {
162  octave_idx_type a_nr = a.rows ();
163  octave_idx_type a_nc = a.cols ();
164 
165  if (a_nr != a_nc)
166  (*current_liboctave_error_handler) ("SCHUR requires square matrix");
167 
168  if (a_nr == 0)
169  {
170  schur_mat.clear ();
171  unitary_mat.clear ();
172  return 0;
173  }
174 
175  // Workspace requirements may need to be fixed if any of the
176  // following change.
177 
178  char jobvs;
179  char sense = 'N';
180  char sort = 'N';
181 
182  if (calc_unitary)
183  jobvs = 'V';
184  else
185  jobvs = 'N';
186 
187  char ord_char = ord.empty () ? 'U' : ord[0];
188 
189  if (ord_char == 'A' || ord_char == 'D' || ord_char == 'a' || ord_char == 'd')
190  sort = 'S';
191 
192  volatile float_selector selector = 0;
193  if (ord_char == 'A' || ord_char == 'a')
194  selector = select_ana<float>;
195  else if (ord_char == 'D' || ord_char == 'd')
196  selector = select_dig<float>;
197 
198  octave_idx_type n = a_nc;
199  octave_idx_type lwork = 8 * n;
200  octave_idx_type liwork = 1;
201  octave_idx_type info;
202  octave_idx_type sdim;
203  float rconde;
204  float rcondv;
205 
206  schur_mat = a;
207 
208  if (calc_unitary)
209  unitary_mat.clear (n, n);
210 
211  float *s = schur_mat.fortran_vec ();
212  float *q = unitary_mat.fortran_vec ();
213 
214  Array<float> wr (dim_vector (n, 1));
215  float *pwr = wr.fortran_vec ();
216 
217  Array<float> wi (dim_vector (n, 1));
218  float *pwi = wi.fortran_vec ();
219 
220  Array<float> work (dim_vector (lwork, 1));
221  float *pwork = work.fortran_vec ();
222 
223  // BWORK is not referenced for the non-ordered Schur routine.
224  octave_idx_type ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n;
225  Array<octave_idx_type> bwork (dim_vector (ntmp, 1));
226  octave_idx_type *pbwork = bwork.fortran_vec ();
227 
228  Array<octave_idx_type> iwork (dim_vector (liwork, 1));
229  octave_idx_type *piwork = iwork.fortran_vec ();
230 
231  F77_XFCN (sgeesx, SGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1),
232  F77_CONST_CHAR_ARG2 (&sort, 1),
233  selector,
234  F77_CONST_CHAR_ARG2 (&sense, 1),
235  n, s, n, sdim, pwr, pwi, q, n, rconde, rcondv,
236  pwork, lwork, piwork, liwork, pbwork, info
237  F77_CHAR_ARG_LEN (1)
238  F77_CHAR_ARG_LEN (1)
239  F77_CHAR_ARG_LEN (1)));
240 
241  return info;
242  }
243 
244  template <>
247  bool calc_unitary)
248  {
249  octave_idx_type a_nr = a.rows ();
250  octave_idx_type a_nc = a.cols ();
251 
252  if (a_nr != a_nc)
253  (*current_liboctave_error_handler) ("SCHUR requires square matrix");
254 
255  if (a_nr == 0)
256  {
257  schur_mat.clear ();
258  unitary_mat.clear ();
259  return 0;
260  }
261 
262  // Workspace requirements may need to be fixed if any of the
263  // following change.
264 
265  char jobvs;
266  char sense = 'N';
267  char sort = 'N';
268 
269  if (calc_unitary)
270  jobvs = 'V';
271  else
272  jobvs = 'N';
273 
274  char ord_char = ord.empty () ? 'U' : ord[0];
275 
276  if (ord_char == 'A' || ord_char == 'D' || ord_char == 'a' || ord_char == 'd')
277  sort = 'S';
278 
279  volatile complex_selector selector = 0;
280  if (ord_char == 'A' || ord_char == 'a')
281  selector = select_ana<Complex>;
282  else if (ord_char == 'D' || ord_char == 'd')
283  selector = select_dig<Complex>;
284 
285  octave_idx_type n = a_nc;
286  octave_idx_type lwork = 8 * n;
287  octave_idx_type info;
288  octave_idx_type sdim;
289  double rconde;
290  double rcondv;
291 
292  schur_mat = a;
293  if (calc_unitary)
294  unitary_mat.clear (n, n);
295 
296  Complex *s = schur_mat.fortran_vec ();
297  Complex *q = unitary_mat.fortran_vec ();
298 
299  Array<double> rwork (dim_vector (n, 1));
300  double *prwork = rwork.fortran_vec ();
301 
302  Array<Complex> w (dim_vector (n, 1));
303  Complex *pw = w.fortran_vec ();
304 
305  Array<Complex> work (dim_vector (lwork, 1));
306  Complex *pwork = work.fortran_vec ();
307 
308  // BWORK is not referenced for non-ordered Schur.
309  octave_idx_type ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n;
310  Array<octave_idx_type> bwork (dim_vector (ntmp, 1));
311  octave_idx_type *pbwork = bwork.fortran_vec ();
312 
313  F77_XFCN (zgeesx, ZGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1),
314  F77_CONST_CHAR_ARG2 (&sort, 1),
315  selector,
316  F77_CONST_CHAR_ARG2 (&sense, 1),
317  n, F77_DBLE_CMPLX_ARG (s), n, sdim, F77_DBLE_CMPLX_ARG (pw),
318  F77_DBLE_CMPLX_ARG (q), n, rconde, rcondv,
319  F77_DBLE_CMPLX_ARG (pwork), lwork, prwork, pbwork, info
320  F77_CHAR_ARG_LEN (1)
321  F77_CHAR_ARG_LEN (1)
322  F77_CHAR_ARG_LEN (1)));
323 
324  return info;
325  }
326 
327  template <>
329  rsf2csf<ComplexMatrix, Matrix> (const Matrix& s_arg, const Matrix& u_arg)
330  {
331  ComplexMatrix s (s_arg);
332  ComplexMatrix u (u_arg);
333 
334  octave_idx_type n = s.rows ();
335 
336  if (s.columns () != n || u.rows () != n || u.columns () != n)
338  ("rsf2csf: inconsistent matrix dimensions");
339 
340  if (n > 0)
341  {
342  OCTAVE_LOCAL_BUFFER (double, c, n-1);
343  OCTAVE_LOCAL_BUFFER (double, sx, n-1);
344 
345  F77_XFCN (zrsf2csf, ZRSF2CSF, (n, F77_DBLE_CMPLX_ARG (s.fortran_vec ()),
346  F77_DBLE_CMPLX_ARG (u.fortran_vec ()), c, sx));
347  }
348 
349  return schur<ComplexMatrix> (s, u);
350  }
351 
352  template <>
355  const std::string& ord, bool calc_unitary)
356  {
357  octave_idx_type a_nr = a.rows ();
358  octave_idx_type a_nc = a.cols ();
359 
360  if (a_nr != a_nc)
361  (*current_liboctave_error_handler) ("SCHUR requires square matrix");
362 
363  if (a_nr == 0)
364  {
365  schur_mat.clear ();
366  unitary_mat.clear ();
367  return 0;
368  }
369 
370  // Workspace requirements may need to be fixed if any of the
371  // following change.
372 
373  char jobvs;
374  char sense = 'N';
375  char sort = 'N';
376 
377  if (calc_unitary)
378  jobvs = 'V';
379  else
380  jobvs = 'N';
381 
382  char ord_char = ord.empty () ? 'U' : ord[0];
383 
384  if (ord_char == 'A' || ord_char == 'D' || ord_char == 'a' || ord_char == 'd')
385  sort = 'S';
386 
387  volatile float_complex_selector selector = 0;
388  if (ord_char == 'A' || ord_char == 'a')
389  selector = select_ana<FloatComplex>;
390  else if (ord_char == 'D' || ord_char == 'd')
391  selector = select_dig<FloatComplex>;
392 
393  octave_idx_type n = a_nc;
394  octave_idx_type lwork = 8 * n;
395  octave_idx_type info;
396  octave_idx_type sdim;
397  float rconde;
398  float rcondv;
399 
400  schur_mat = a;
401  if (calc_unitary)
402  unitary_mat.clear (n, n);
403 
404  FloatComplex *s = schur_mat.fortran_vec ();
405  FloatComplex *q = unitary_mat.fortran_vec ();
406 
407  Array<float> rwork (dim_vector (n, 1));
408  float *prwork = rwork.fortran_vec ();
409 
411  FloatComplex *pw = w.fortran_vec ();
412 
413  Array<FloatComplex> work (dim_vector (lwork, 1));
414  FloatComplex *pwork = work.fortran_vec ();
415 
416  // BWORK is not referenced for non-ordered Schur.
417  octave_idx_type ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n;
418  Array<octave_idx_type> bwork (dim_vector (ntmp, 1));
419  octave_idx_type *pbwork = bwork.fortran_vec ();
420 
421  F77_XFCN (cgeesx, CGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1),
422  F77_CONST_CHAR_ARG2 (&sort, 1),
423  selector,
424  F77_CONST_CHAR_ARG2 (&sense, 1),
425  n, F77_CMPLX_ARG (s), n, sdim, F77_CMPLX_ARG (pw), F77_CMPLX_ARG (q), n, rconde,
426  rcondv,
427  F77_CMPLX_ARG (pwork), lwork, prwork, pbwork, info
428  F77_CHAR_ARG_LEN (1)
429  F77_CHAR_ARG_LEN (1)
430  F77_CHAR_ARG_LEN (1)));
431 
432  return info;
433  }
434 
435  template <>
438  const FloatMatrix& u_arg)
439  {
440  FloatComplexMatrix s (s_arg);
441  FloatComplexMatrix u (u_arg);
442 
443  octave_idx_type n = s.rows ();
444 
445  if (s.columns () != n || u.rows () != n || u.columns () != n)
447  ("rsf2csf: inconsistent matrix dimensions");
448 
449  if (n > 0)
450  {
451  OCTAVE_LOCAL_BUFFER (float, c, n-1);
452  OCTAVE_LOCAL_BUFFER (float, sx, n-1);
453 
454  F77_XFCN (crsf2csf, CRSF2CSF, (n, F77_CMPLX_ARG (s.fortran_vec ()),
455  F77_CMPLX_ARG (u.fortran_vec ()), c, sx));
456  }
457 
458  return schur<FloatComplexMatrix> (s, u);
459  }
460 
461  // Instantiations we need.
462 
463  template class schur<ComplexMatrix>;
464 
465  template class schur<FloatComplexMatrix>;
466 
467  template class schur<FloatMatrix>;
468 
469  template class schur<Matrix>;
470  }
471 }
static octave_idx_type select_ana(const T &a, const T &)
Definition: schur.cc:43
octave_idx_type(* float_complex_selector)(const FloatComplex &)
Octave interface to the compression and uncompression libraries.
Definition: aepbalance.cc:47
OCTAVE_NORETURN liboctave_error_handler current_liboctave_error_handler
Definition: lo-error.c:38
#define F77_DBLE_CMPLX_ARG(x)
Definition: f77-fcn.h:345
octave_idx_type init(const T &a, const std::string &ord, bool calc_unitary)
Definition: mx-defs.h:71
u
Definition: lu.cc:138
subroutine zrsf2csf(n, t, u, c, s)
Definition: zrsf2csf.f:22
s
Definition: file-io.cc:2682
#define F77_XFCN(f, F, args)
Definition: f77-fcn.h:52
subroutine crsf2csf(n, t, u, c, s)
Definition: crsf2csf.f:22
octave_idx_type a_nc
Definition: sylvester.cc:72
octave_idx_type rows(void) const
Definition: Array.h:401
calling an anonymous function involves an overhead quite comparable to the overhead of an m file function Passing a handle to a built in function is because the interpreter is not involved in the internal loop For a
Definition: cellfun.cc:398
octave_idx_type a_nr
Definition: sylvester.cc:71
std::complex< double > w(std::complex< double > z, double relerr=0)
static octave_idx_type select_dig(const T &a, const T &b)
Definition: schur.cc:50
Definition: dMatrix.h:37
the sparsity preserving column transformation such that that defines the pivoting threshold can be given in which case it defines the c
Definition: lu.cc:138
schur< FloatComplexMatrix > rsf2csf< FloatComplexMatrix, FloatMatrix >(const FloatMatrix &s_arg, const FloatMatrix &u_arg)
Definition: schur.cc:437
schur< ComplexMatrix > rsf2csf< ComplexMatrix, Matrix >(const Matrix &s_arg, const Matrix &u_arg)
Definition: schur.cc:329
#define F77_CMPLX_ARG(x)
Definition: f77-fcn.h:339
octave_idx_type(* float_selector)(const float &, const float &)
octave_idx_type(* complex_selector)(const Complex &)
static double wi[256]
Definition: randmtzig.cc:440
OCTAVE_EXPORT octave_value_list return the value of the option it must match the dimension of the state and the relative tolerance must also be a vector of the same length tem it must match the dimension of the state and the absolute tolerance must also be a vector of the same length The local error test applied at each integration step is xample roup abs(local error in x(i))<
b
Definition: cellfun.cc:398
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:200
std::complex< float > FloatComplex
Definition: oct-cmplx.h:32
std::complex< double > Complex
Definition: oct-cmplx.h:31
const T * fortran_vec(void) const
Definition: Array.h:584
octave_idx_type cols(void) const
Definition: Array.h:409
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:854
octave_idx_type(* double_selector)(const double &, const double &)
octave_idx_type columns(void) const
Definition: Array.h:410