GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
schur.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1994-2018 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
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 "Array.h"
28 #include "CMatrix.h"
29 #include "dMatrix.h"
30 #include "fCMatrix.h"
31 #include "fMatrix.h"
32 #include "lo-error.h"
33 #include "lo-lapack-proto.h"
34 #include "oct-locbuf.h"
35 #include "schur.h"
36 
37 namespace octave
38 {
39  namespace math
40  {
41  // For real types.
42 
43  static F77_INT
44  select_ana (const double& a, const double&)
45  {
46  return (a < 0.0);
47  }
48 
49  static F77_INT
50  select_dig (const double& a, const double& b)
51  {
52  return (hypot (a, b) < 1.0);
53  }
54 
55  static F77_INT
56  select_ana (const float& a, const float&)
57  {
58  return (a < 0.0);
59  }
60 
61  static F77_INT
62  select_dig (const float& a, const float& b)
63  {
64  return (hypot (a, b) < 1.0);
65  }
66 
67  // For complex types.
68 
69  static F77_INT
70  select_ana (const F77_DBLE_CMPLX& a_arg)
71  {
72  const Complex a = reinterpret_cast<const Complex&> (a_arg);
73  return a.real () < 0.0;
74  }
75 
76  static F77_INT
77  select_dig (const F77_DBLE_CMPLX& a_arg)
78  {
79  const Complex& a = reinterpret_cast<const Complex&> (a_arg);
80  return (abs (a) < 1.0);
81  }
82 
83  static F77_INT
84  select_ana (const F77_CMPLX& a_arg)
85  {
86  const FloatComplex& a = reinterpret_cast<const FloatComplex&> (a_arg);
87  return a.real () < 0.0;
88  }
89 
90  static F77_INT
91  select_dig (const F77_CMPLX& a_arg)
92  {
93  const FloatComplex& a = reinterpret_cast<const FloatComplex&> (a_arg);
94  return (abs (a) < 1.0);
95  }
96 
97  template <>
98  F77_INT
99  schur<Matrix>::init (const Matrix& a, const std::string& ord, bool calc_unitary)
100  {
101  F77_INT a_nr = to_f77_int (a.rows ());
102  F77_INT a_nc = to_f77_int (a.cols ());
103 
104  if (a_nr != a_nc)
105  (*current_liboctave_error_handler) ("schur: requires square matrix");
106 
107  if (a_nr == 0)
108  {
109  schur_mat.clear ();
110  unitary_mat.clear ();
111  return 0;
112  }
113 
114  // Workspace requirements may need to be fixed if any of the
115  // following change.
116 
117  char jobvs;
118  char sense = 'N';
119  char sort = 'N';
120 
121  if (calc_unitary)
122  jobvs = 'V';
123  else
124  jobvs = 'N';
125 
126  char ord_char = (ord.empty () ? 'U' : ord[0]);
127 
128  if (ord_char == 'A' || ord_char == 'D' || ord_char == 'a' || ord_char == 'd')
129  sort = 'S';
130 
131  volatile double_selector selector = nullptr;
132  if (ord_char == 'A' || ord_char == 'a')
133  selector = select_ana;
134  else if (ord_char == 'D' || ord_char == 'd')
135  selector = select_dig;
136 
137  F77_INT n = a_nc;
138  F77_INT lwork = 8 * n;
139  F77_INT liwork = 1;
140  F77_INT info;
141  F77_INT sdim;
142  double rconde;
143  double rcondv;
144 
145  schur_mat = a;
146 
147  if (calc_unitary)
148  unitary_mat.clear (n, n);
149 
150  double *s = schur_mat.fortran_vec ();
151  double *q = unitary_mat.fortran_vec ();
152 
153  Array<double> wr (dim_vector (n, 1));
154  double *pwr = wr.fortran_vec ();
155 
156  Array<double> wi (dim_vector (n, 1));
157  double *pwi = wi.fortran_vec ();
158 
159  Array<double> work (dim_vector (lwork, 1));
160  double *pwork = work.fortran_vec ();
161 
162  // BWORK is not referenced for the non-ordered Schur routine.
163  F77_INT ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n;
164  Array<F77_INT> bwork (dim_vector (ntmp, 1));
165  F77_INT *pbwork = bwork.fortran_vec ();
166 
167  Array<F77_INT> iwork (dim_vector (liwork, 1));
168  F77_INT *piwork = iwork.fortran_vec ();
169 
170  F77_XFCN (dgeesx, DGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1),
171  F77_CONST_CHAR_ARG2 (&sort, 1),
172  selector,
173  F77_CONST_CHAR_ARG2 (&sense, 1),
174  n, s, n, sdim, pwr, pwi, q, n, rconde, rcondv,
175  pwork, lwork, piwork, liwork, pbwork, info
176  F77_CHAR_ARG_LEN (1)
177  F77_CHAR_ARG_LEN (1)
178  F77_CHAR_ARG_LEN (1)));
179 
180  return info;
181  }
182 
183  template <>
184  F77_INT
186  bool calc_unitary)
187  {
188  F77_INT a_nr = to_f77_int (a.rows ());
189  F77_INT a_nc = to_f77_int (a.cols ());
190 
191  if (a_nr != a_nc)
192  (*current_liboctave_error_handler) ("SCHUR requires square matrix");
193 
194  if (a_nr == 0)
195  {
196  schur_mat.clear ();
197  unitary_mat.clear ();
198  return 0;
199  }
200 
201  // Workspace requirements may need to be fixed if any of the
202  // following change.
203 
204  char jobvs;
205  char sense = 'N';
206  char sort = 'N';
207 
208  if (calc_unitary)
209  jobvs = 'V';
210  else
211  jobvs = 'N';
212 
213  char ord_char = (ord.empty () ? 'U' : ord[0]);
214 
215  if (ord_char == 'A' || ord_char == 'D' || ord_char == 'a' || ord_char == 'd')
216  sort = 'S';
217 
218  volatile float_selector selector = nullptr;
219  if (ord_char == 'A' || ord_char == 'a')
220  selector = select_ana;
221  else if (ord_char == 'D' || ord_char == 'd')
222  selector = select_dig;
223 
224  F77_INT n = a_nc;
225  F77_INT lwork = 8 * n;
226  F77_INT liwork = 1;
227  F77_INT info;
228  F77_INT sdim;
229  float rconde;
230  float rcondv;
231 
232  schur_mat = a;
233 
234  if (calc_unitary)
235  unitary_mat.clear (n, n);
236 
237  float *s = schur_mat.fortran_vec ();
238  float *q = unitary_mat.fortran_vec ();
239 
240  Array<float> wr (dim_vector (n, 1));
241  float *pwr = wr.fortran_vec ();
242 
243  Array<float> wi (dim_vector (n, 1));
244  float *pwi = wi.fortran_vec ();
245 
246  Array<float> work (dim_vector (lwork, 1));
247  float *pwork = work.fortran_vec ();
248 
249  // BWORK is not referenced for the non-ordered Schur routine.
250  F77_INT ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n;
251  Array<F77_INT> bwork (dim_vector (ntmp, 1));
252  F77_INT *pbwork = bwork.fortran_vec ();
253 
254  Array<F77_INT> iwork (dim_vector (liwork, 1));
255  F77_INT *piwork = iwork.fortran_vec ();
256 
257  F77_XFCN (sgeesx, SGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1),
258  F77_CONST_CHAR_ARG2 (&sort, 1),
259  selector,
260  F77_CONST_CHAR_ARG2 (&sense, 1),
261  n, s, n, sdim, pwr, pwi, q, n, rconde, rcondv,
262  pwork, lwork, piwork, liwork, pbwork, info
263  F77_CHAR_ARG_LEN (1)
264  F77_CHAR_ARG_LEN (1)
265  F77_CHAR_ARG_LEN (1)));
266 
267  return info;
268  }
269 
270  template <>
271  F77_INT
273  bool calc_unitary)
274  {
275  F77_INT a_nr = to_f77_int (a.rows ());
276  F77_INT a_nc = to_f77_int (a.cols ());
277 
278  if (a_nr != a_nc)
279  (*current_liboctave_error_handler) ("SCHUR requires square matrix");
280 
281  if (a_nr == 0)
282  {
283  schur_mat.clear ();
284  unitary_mat.clear ();
285  return 0;
286  }
287 
288  // Workspace requirements may need to be fixed if any of the
289  // following change.
290 
291  char jobvs;
292  char sense = 'N';
293  char sort = 'N';
294 
295  if (calc_unitary)
296  jobvs = 'V';
297  else
298  jobvs = 'N';
299 
300  char ord_char = (ord.empty () ? 'U' : ord[0]);
301 
302  if (ord_char == 'A' || ord_char == 'D' || ord_char == 'a' || ord_char == 'd')
303  sort = 'S';
304 
305  volatile complex_selector selector = nullptr;
306  if (ord_char == 'A' || ord_char == 'a')
307  selector = select_ana;
308  else if (ord_char == 'D' || ord_char == 'd')
309  selector = select_dig;
310 
311  F77_INT n = a_nc;
312  F77_INT lwork = 8 * n;
313  F77_INT info;
314  F77_INT sdim;
315  double rconde;
316  double rcondv;
317 
318  schur_mat = a;
319  if (calc_unitary)
320  unitary_mat.clear (n, n);
321 
322  Complex *s = schur_mat.fortran_vec ();
323  Complex *q = unitary_mat.fortran_vec ();
324 
325  Array<double> rwork (dim_vector (n, 1));
326  double *prwork = rwork.fortran_vec ();
327 
328  Array<Complex> w (dim_vector (n, 1));
329  Complex *pw = w.fortran_vec ();
330 
331  Array<Complex> work (dim_vector (lwork, 1));
332  Complex *pwork = work.fortran_vec ();
333 
334  // BWORK is not referenced for non-ordered Schur.
335  F77_INT ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n;
336  Array<F77_INT> bwork (dim_vector (ntmp, 1));
337  F77_INT *pbwork = bwork.fortran_vec ();
338 
339  F77_XFCN (zgeesx, ZGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1),
340  F77_CONST_CHAR_ARG2 (&sort, 1),
341  selector,
342  F77_CONST_CHAR_ARG2 (&sense, 1),
343  n, F77_DBLE_CMPLX_ARG (s), n, sdim, F77_DBLE_CMPLX_ARG (pw),
344  F77_DBLE_CMPLX_ARG (q), n, rconde, rcondv,
345  F77_DBLE_CMPLX_ARG (pwork), lwork, prwork, pbwork, info
346  F77_CHAR_ARG_LEN (1)
347  F77_CHAR_ARG_LEN (1)
348  F77_CHAR_ARG_LEN (1)));
349 
350  return info;
351  }
352 
353  template <>
355  rsf2csf<ComplexMatrix, Matrix> (const Matrix& s_arg, const Matrix& u_arg)
356  {
357  ComplexMatrix s (s_arg);
358  ComplexMatrix u (u_arg);
359 
360  F77_INT n = to_f77_int (s.rows ());
361 
362  if (s.columns () != n || u.rows () != n || u.columns () != n)
364  ("rsf2csf: inconsistent matrix dimensions");
365 
366  if (n > 0)
367  {
368  OCTAVE_LOCAL_BUFFER (double, c, n-1);
369  OCTAVE_LOCAL_BUFFER (double, sx, n-1);
370 
371  F77_XFCN (zrsf2csf, ZRSF2CSF, (n, F77_DBLE_CMPLX_ARG (s.fortran_vec ()),
372  F77_DBLE_CMPLX_ARG (u.fortran_vec ()), c, sx));
373  }
374 
375  return schur<ComplexMatrix> (s, u);
376  }
377 
378  template <>
379  F77_INT
381  const std::string& ord, bool calc_unitary)
382  {
383  F77_INT a_nr = to_f77_int (a.rows ());
384  F77_INT a_nc = to_f77_int (a.cols ());
385 
386  if (a_nr != a_nc)
387  (*current_liboctave_error_handler) ("SCHUR requires square matrix");
388 
389  if (a_nr == 0)
390  {
391  schur_mat.clear ();
392  unitary_mat.clear ();
393  return 0;
394  }
395 
396  // Workspace requirements may need to be fixed if any of the
397  // following change.
398 
399  char jobvs;
400  char sense = 'N';
401  char sort = 'N';
402 
403  if (calc_unitary)
404  jobvs = 'V';
405  else
406  jobvs = 'N';
407 
408  char ord_char = (ord.empty () ? 'U' : ord[0]);
409 
410  if (ord_char == 'A' || ord_char == 'D' || ord_char == 'a' || ord_char == 'd')
411  sort = 'S';
412 
413  volatile float_complex_selector selector = nullptr;
414  if (ord_char == 'A' || ord_char == 'a')
415  selector = select_ana;
416  else if (ord_char == 'D' || ord_char == 'd')
417  selector = select_dig;
418 
419  F77_INT n = a_nc;
420  F77_INT lwork = 8 * n;
421  F77_INT info;
422  F77_INT sdim;
423  float rconde;
424  float rcondv;
425 
426  schur_mat = a;
427  if (calc_unitary)
428  unitary_mat.clear (n, n);
429 
430  FloatComplex *s = schur_mat.fortran_vec ();
431  FloatComplex *q = unitary_mat.fortran_vec ();
432 
433  Array<float> rwork (dim_vector (n, 1));
434  float *prwork = rwork.fortran_vec ();
435 
437  FloatComplex *pw = w.fortran_vec ();
438 
439  Array<FloatComplex> work (dim_vector (lwork, 1));
440  FloatComplex *pwork = work.fortran_vec ();
441 
442  // BWORK is not referenced for non-ordered Schur.
443  F77_INT ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n;
444  Array<F77_INT> bwork (dim_vector (ntmp, 1));
445  F77_INT *pbwork = bwork.fortran_vec ();
446 
447  F77_XFCN (cgeesx, CGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1),
448  F77_CONST_CHAR_ARG2 (&sort, 1),
449  selector,
450  F77_CONST_CHAR_ARG2 (&sense, 1),
451  n, F77_CMPLX_ARG (s), n, sdim, F77_CMPLX_ARG (pw), F77_CMPLX_ARG (q), n, rconde,
452  rcondv,
453  F77_CMPLX_ARG (pwork), lwork, prwork, pbwork, info
454  F77_CHAR_ARG_LEN (1)
455  F77_CHAR_ARG_LEN (1)
456  F77_CHAR_ARG_LEN (1)));
457 
458  return info;
459  }
460 
461  template <>
464  const FloatMatrix& u_arg)
465  {
466  FloatComplexMatrix s (s_arg);
467  FloatComplexMatrix u (u_arg);
468 
469  F77_INT n = to_f77_int (s.rows ());
470 
471  if (s.columns () != n || u.rows () != n || u.columns () != n)
473  ("rsf2csf: inconsistent matrix dimensions");
474 
475  if (n > 0)
476  {
477  OCTAVE_LOCAL_BUFFER (float, c, n-1);
478  OCTAVE_LOCAL_BUFFER (float, sx, n-1);
479 
480  F77_XFCN (crsf2csf, CRSF2CSF, (n, F77_CMPLX_ARG (s.fortran_vec ()),
481  F77_CMPLX_ARG (u.fortran_vec ()), c, sx));
482  }
483 
484  return schur<FloatComplexMatrix> (s, u);
485  }
486 
487  // Instantiations we need.
488 
489  template class schur<ComplexMatrix>;
490 
491  template class schur<FloatComplexMatrix>;
492 
493  template class schur<FloatMatrix>;
494 
495  template class schur<Matrix>;
496  }
497 }
double _Complex F77_DBLE_CMPLX
Definition: f77-fcn.h:303
F77_INT(* double_selector)(const F77_DBLE &, const F77_DBLE &)
OCTAVE_NORETURN liboctave_error_handler current_liboctave_error_handler
Definition: lo-error.c:38
#define F77_DBLE_CMPLX_ARG(x)
Definition: f77-fcn.h:315
const T * fortran_vec(void) const
Definition: Array.h:584
static T abs(T x)
Definition: pr-output.cc:1696
static F77_INT select_ana(const double &a, const double &)
Definition: schur.cc:44
static F77_INT select_dig(const double &a, const double &b)
Definition: schur.cc:50
u
Definition: lu.cc:138
subroutine zrsf2csf(n, t, u, c, s)
Definition: zrsf2csf.f:23
nd example oindent opens the file binary numeric values will be read assuming they are stored in IEEE format with the least significant bit and then converted to the native representation Opening a file that is already open simply opens it again and returns a separate file id It is not an error to open a file several though writing to the same file through several different file ids may produce unexpected results The possible values of text mode reading and writing automatically converts linefeeds to the appropriate line end character for the you may append a you must also open the file in binary mode The parameter conversions are currently only supported for and permissions will be set to and then everything is written in a single operation This is very efficient and improves performance c
Definition: file-io.cc:587
s
Definition: file-io.cc:2729
#define F77_XFCN(f, F, args)
Definition: f77-fcn.h:41
subroutine crsf2csf(n, t, u, c, s)
Definition: crsf2csf.f:23
octave_idx_type a_nc
Definition: sylvester.cc:74
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:400
float _Complex F77_CMPLX
Definition: f77-fcn.h:304
octave_idx_type a_nr
Definition: sylvester.cc:73
std::complex< double > w(std::complex< double > z, double relerr=0)
F77_INT(* float_selector)(const F77_REAL &, const F77_REAL &)
Definition: dMatrix.h:36
schur< FloatComplexMatrix > rsf2csf< FloatComplexMatrix, FloatMatrix >(const FloatMatrix &s_arg, const FloatMatrix &u_arg)
Definition: schur.cc:463
Definition: mx-defs.h:73
schur< ComplexMatrix > rsf2csf< ComplexMatrix, Matrix >(const Matrix &s_arg, const Matrix &u_arg)
Definition: schur.cc:355
#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
b
Definition: cellfun.cc:400
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:41
F77_INT(* float_complex_selector)(const F77_CMPLX &)
std::complex< float > FloatComplex
Definition: oct-cmplx.h:32
F77_INT(* complex_selector)(const F77_DBLE_CMPLX &)
octave_f77_int_type init(const T &a, const std::string &ord, bool calc_unitary)
std::complex< double > Complex
Definition: oct-cmplx.h:31
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:888