# HG changeset patch # User John W. Eaton # Date 1455584772 18000 # Node ID e69eaee287374979d7d9378cdde4f5e47bca5067 # Parent f780d057a3ec550a8a0f4ff808a058359b36bfaf make better use of templates for Schur decomposition * liboctave/numeric/schur.h, liboctave/numeric/schur.cc: New files generated from SCHUR.h, SCHUR.cc, CmplxSCHUR.h, CmplxSCHUR.cc, dbleSCHUR.h, dbleSCHUR.cc, fCmplxSCHUR.h, fCmplxSCHUR.cc, floatSCHUR.h, and floatSCHUR.cc and making them templates. * liboctave/numeric/module.mk: Update. * libinterp/corefcn/schur.cc, sqrtm.cc, CMatrix.cc, dMatrix.cc, fCMatrix.cc, fMatrix.cc, mx-defs.h, mx-ext.h: Use new template classes and header file. diff -r f780d057a3ec -r e69eaee28737 libinterp/corefcn/schur.cc --- a/libinterp/corefcn/schur.cc Thu Jan 14 19:59:52 2016 +1100 +++ b/libinterp/corefcn/schur.cc Mon Feb 15 20:06:12 2016 -0500 @@ -26,10 +26,7 @@ #include -#include "CmplxSCHUR.h" -#include "dbleSCHUR.h" -#include "fCmplxSCHUR.h" -#include "floatSCHUR.h" +#include "schur.h" #include "defun.h" #include "error.h" @@ -182,12 +179,12 @@ if (nargout <= 1) { - FloatSCHUR result (tmp, ord, false); + schur result (tmp, ord, false); retval = ovl (result.schur_matrix ()); } else { - FloatSCHUR result (tmp, ord, true); + schur result (tmp, ord, true); retval = ovl (result.unitary_matrix (), result.schur_matrix ()); } @@ -198,12 +195,12 @@ if (nargout <= 1) { - FloatComplexSCHUR result (ctmp, ord, false); + schur result (ctmp, ord, false); retval = ovl (mark_upper_triangular (result.schur_matrix ())); } else { - FloatComplexSCHUR result (ctmp, ord, true); + schur result (ctmp, ord, true); retval = ovl (result.unitary_matrix (), mark_upper_triangular (result.schur_matrix ())); } @@ -217,12 +214,12 @@ if (nargout <= 1) { - SCHUR result (tmp, ord, false); + schur result (tmp, ord, false); retval = ovl (result.schur_matrix ()); } else { - SCHUR result (tmp, ord, true); + schur result (tmp, ord, true); retval = ovl (result.unitary_matrix (), result.schur_matrix ()); } @@ -233,12 +230,12 @@ if (nargout <= 1) { - ComplexSCHUR result (ctmp, ord, false); + schur result (ctmp, ord, false); retval = ovl (mark_upper_triangular (result.schur_matrix ())); } else { - ComplexSCHUR result (ctmp, ord, true); + schur result (ctmp, ord, true); retval = ovl (result.unitary_matrix (), mark_upper_triangular (result.schur_matrix ())); } @@ -304,7 +301,8 @@ FloatMatrix u = args(0).float_matrix_value (); FloatMatrix t = args(1).float_matrix_value (); - FloatComplexSCHUR cs (FloatSCHUR (t, u)); + schur cs + = rsf2csf (t, u); return ovl (cs.unitary_matrix (), cs.schur_matrix ()); } @@ -313,7 +311,7 @@ Matrix u = args(0).matrix_value (); Matrix t = args(1).matrix_value (); - ComplexSCHUR cs (SCHUR (t, u)); + schur cs = rsf2csf (t, u); return ovl (cs.unitary_matrix (), cs.schur_matrix ()); } diff -r f780d057a3ec -r e69eaee28737 libinterp/corefcn/sqrtm.cc --- a/libinterp/corefcn/sqrtm.cc Thu Jan 14 19:59:52 2016 +1100 +++ b/libinterp/corefcn/sqrtm.cc Mon Feb 15 20:06:12 2016 -0500 @@ -27,8 +27,7 @@ #include -#include "CmplxSCHUR.h" -#include "fCmplxSCHUR.h" +#include "schur.h" #include "lo-ieee.h" #include "lo-mappers.h" #include "oct-norm.h" @@ -177,9 +176,9 @@ do { - ComplexSCHUR schur (x, "", true); - x = schur.schur_matrix (); - u = schur.unitary_matrix (); + ComplexSCHUR schur_fact (x, "", true); + x = schur_fact.schur_matrix (); + u = schur_fact.unitary_matrix (); } while (0); // schur no longer needed. @@ -236,10 +235,10 @@ // sqrtm of a diagonal matrix is just sqrt. retval(0) = arg.sqrt (); else if (arg.is_single_type ()) - retval(0) = do_sqrtm - (arg); + retval(0) = do_sqrtm > (arg); else if (arg.is_numeric_type ()) - retval(0) = do_sqrtm (arg); + retval(0) = do_sqrtm > (arg); if (nargout > 1) { diff -r f780d057a3ec -r e69eaee28737 liboctave/array/CMatrix.cc --- a/liboctave/array/CMatrix.cc Thu Jan 14 19:59:52 2016 +1100 +++ b/liboctave/array/CMatrix.cc Mon Feb 15 20:06:12 2016 -0500 @@ -46,7 +46,7 @@ #include "CDiagMatrix.h" #include "dDiagMatrix.h" #include "CmplxCHOL.h" -#include "CmplxSCHUR.h" +#include "schur.h" #include "CmplxSVD.h" #include "DET.h" #include "f77-fcn.h" @@ -3487,8 +3487,8 @@ // Compute Schur decompositions - ComplexSCHUR as (a, "U"); - ComplexSCHUR bs (b, "U"); + schur as (a, "U"); + schur bs (b, "U"); // Transform c to new coordinates. diff -r f780d057a3ec -r e69eaee28737 liboctave/array/dMatrix.cc --- a/liboctave/array/dMatrix.cc Thu Jan 14 19:59:52 2016 +1100 +++ b/liboctave/array/dMatrix.cc Mon Feb 15 20:06:12 2016 -0500 @@ -44,7 +44,7 @@ #include "CColVector.h" #include "PermMatrix.h" #include "DET.h" -#include "dbleSCHUR.h" +#include "schur.h" #include "dbleSVD.h" #include "dbleCHOL.h" #include "f77-fcn.h" @@ -2953,8 +2953,8 @@ // Compute Schur decompositions. - SCHUR as (a, "U"); - SCHUR bs (b, "U"); + schur as (a, "U"); + schur bs (b, "U"); // Transform c to new coordinates. diff -r f780d057a3ec -r e69eaee28737 liboctave/array/fCMatrix.cc --- a/liboctave/array/fCMatrix.cc Thu Jan 14 19:59:52 2016 +1100 +++ b/liboctave/array/fCMatrix.cc Mon Feb 15 20:06:12 2016 -0500 @@ -46,7 +46,7 @@ #include "fCColVector.h" #include "fCRowVector.h" #include "fCmplxCHOL.h" -#include "fCmplxSCHUR.h" +#include "schur.h" #include "fCmplxSVD.h" #include "functor.h" #include "lo-error.h" @@ -3501,8 +3501,8 @@ // Compute Schur decompositions - FloatComplexSCHUR as (a, "U"); - FloatComplexSCHUR bs (b, "U"); + schur as (a, "U"); + schur bs (b, "U"); // Transform c to new coordinates. diff -r f780d057a3ec -r e69eaee28737 liboctave/array/fMatrix.cc --- a/liboctave/array/fMatrix.cc Thu Jan 14 19:59:52 2016 +1100 +++ b/liboctave/array/fMatrix.cc Mon Feb 15 20:06:12 2016 -0500 @@ -48,7 +48,7 @@ #include "f77-fcn.h" #include "fMatrix.h" #include "floatCHOL.h" -#include "floatSCHUR.h" +#include "schur.h" #include "floatSVD.h" #include "functor.h" #include "lo-error.h" @@ -2970,8 +2970,8 @@ // Compute Schur decompositions. - FloatSCHUR as (a, "U"); - FloatSCHUR bs (b, "U"); + schur as (a, "U"); + schur bs (b, "U"); // Transform c to new coordinates. diff -r f780d057a3ec -r e69eaee28737 liboctave/numeric/CmplxSCHUR.cc --- a/liboctave/numeric/CmplxSCHUR.cc Thu Jan 14 19:59:52 2016 +1100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,170 +0,0 @@ -/* - -Copyright (C) 1994-2015 John W. Eaton - -This file is part of Octave. - -Octave is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3 of the License, or (at your -option) any later version. - -Octave is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with Octave; see the file COPYING. If not, see -. - -*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "CmplxSCHUR.h" -#include "f77-fcn.h" -#include "lo-error.h" -#include "oct-locbuf.h" - -extern "C" -{ - F77_RET_T - F77_FUNC (zgeesx, ZGEESX) (F77_CONST_CHAR_ARG_DECL, - F77_CONST_CHAR_ARG_DECL, - ComplexSCHUR::select_function, - F77_CONST_CHAR_ARG_DECL, - const octave_idx_type&, Complex*, - const octave_idx_type&, octave_idx_type&, - Complex*, Complex*, const octave_idx_type&, - double&, double&, Complex*, - const octave_idx_type&, double*, - octave_idx_type*, octave_idx_type& - F77_CHAR_ARG_LEN_DECL - F77_CHAR_ARG_LEN_DECL - F77_CHAR_ARG_LEN_DECL); - - F77_RET_T - F77_FUNC (zrsf2csf, ZRSF2CSF) (const octave_idx_type&, Complex *, - Complex *, double *, double *); -} - -static octave_idx_type -select_ana (const Complex& a) -{ - return a.real () < 0.0; -} - -static octave_idx_type -select_dig (const Complex& a) -{ - return (abs (a) < 1.0); -} - -octave_idx_type -ComplexSCHUR::init (const ComplexMatrix& a, const std::string& ord, - bool calc_unitary) -{ - octave_idx_type a_nr = a.rows (); - octave_idx_type a_nc = a.cols (); - - if (a_nr != a_nc) - (*current_liboctave_error_handler) ("ComplexSCHUR requires square matrix"); - - if (a_nr == 0) - { - schur_mat.clear (); - unitary_mat.clear (); - return 0; - } - - // Workspace requirements may need to be fixed if any of the - // following change. - - char jobvs; - char sense = 'N'; - char sort = 'N'; - - if (calc_unitary) - jobvs = 'V'; - else - jobvs = 'N'; - - char ord_char = ord.empty () ? 'U' : ord[0]; - - if (ord_char == 'A' || ord_char == 'D' || ord_char == 'a' || ord_char == 'd') - sort = 'S'; - - if (ord_char == 'A' || ord_char == 'a') - selector = select_ana; - else if (ord_char == 'D' || ord_char == 'd') - selector = select_dig; - else - selector = 0; - - octave_idx_type n = a_nc; - octave_idx_type lwork = 8 * n; - octave_idx_type info; - octave_idx_type sdim; - double rconde; - double rcondv; - - schur_mat = a; - if (calc_unitary) - unitary_mat.clear (n, n); - - Complex *s = schur_mat.fortran_vec (); - Complex *q = unitary_mat.fortran_vec (); - - Array rwork (dim_vector (n, 1)); - double *prwork = rwork.fortran_vec (); - - Array w (dim_vector (n, 1)); - Complex *pw = w.fortran_vec (); - - Array work (dim_vector (lwork, 1)); - Complex *pwork = work.fortran_vec (); - - // BWORK is not referenced for non-ordered Schur. - octave_idx_type ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n; - Array bwork (dim_vector (ntmp, 1)); - octave_idx_type *pbwork = bwork.fortran_vec (); - - F77_XFCN (zgeesx, ZGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1), - F77_CONST_CHAR_ARG2 (&sort, 1), - selector, - F77_CONST_CHAR_ARG2 (&sense, 1), - n, s, n, sdim, pw, q, n, rconde, rcondv, - pwork, lwork, prwork, pbwork, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); - - return info; -} - -ComplexSCHUR::ComplexSCHUR (const ComplexMatrix& s, const ComplexMatrix& u) - : schur_mat (s), unitary_mat (u), selector (0) -{ - octave_idx_type n = s.rows (); - if (s.columns () != n || u.rows () != n || u.columns () != n) - (*current_liboctave_error_handler) - ("schur: inconsistent matrix dimensions"); -} - -ComplexSCHUR::ComplexSCHUR (const SCHUR& s) - : schur_mat (s.schur_matrix ()), unitary_mat (s.unitary_matrix ()), - selector (0) -{ - octave_idx_type n = schur_mat.rows (); - if (n > 0) - { - OCTAVE_LOCAL_BUFFER (double, c, n-1); - OCTAVE_LOCAL_BUFFER (double, sx, n-1); - - F77_XFCN (zrsf2csf, ZRSF2CSF, (n, schur_mat.fortran_vec (), - unitary_mat.fortran_vec (), c, sx)); - } -} diff -r f780d057a3ec -r e69eaee28737 liboctave/numeric/CmplxSCHUR.h --- a/liboctave/numeric/CmplxSCHUR.h Thu Jan 14 19:59:52 2016 +1100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/* - -Copyright (C) 1994-2015 John W. Eaton - -This file is part of Octave. - -Octave is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3 of the License, or (at your -option) any later version. - -Octave is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with Octave; see the file COPYING. If not, see -. - -*/ - -#if ! defined (octave_CmplxSCHUR_h) -#define octave_CmplxSCHUR_h 1 - -#include "octave-config.h" - -#include -#include - -#include "CMatrix.h" -#include "dbleSCHUR.h" - -class -OCTAVE_API -ComplexSCHUR -{ -public: - - ComplexSCHUR (void) : schur_mat (), unitary_mat (), selector (0) { } - - ComplexSCHUR (const ComplexMatrix& a, const std::string& ord, - bool calc_unitary = true) - : schur_mat (), unitary_mat (), selector (0) - { - init (a, ord, calc_unitary); - } - - ComplexSCHUR (const ComplexMatrix& a, const std::string& ord, - octave_idx_type& info, - bool calc_unitary = true) - : schur_mat (), unitary_mat (), selector (0) - { - info = init (a, ord, calc_unitary); - } - - ComplexSCHUR (const ComplexSCHUR& a) - : schur_mat (a.schur_mat), unitary_mat (a.unitary_mat), selector (0) - { } - - ComplexSCHUR (const ComplexMatrix& s, const ComplexMatrix& u); - - ComplexSCHUR (const SCHUR& s); - - ComplexSCHUR& operator = (const ComplexSCHUR& a) - { - if (this != &a) - { - schur_mat = a.schur_mat; - unitary_mat = a.unitary_mat; - } - return *this; - } - - ~ComplexSCHUR (void) { } - - ComplexMatrix schur_matrix (void) const { return schur_mat; } - - ComplexMatrix unitary_matrix (void) const { return unitary_mat; } - - friend std::ostream& operator << (std::ostream& os, const ComplexSCHUR& a); - - typedef octave_idx_type (*select_function) (const Complex&); - -private: - - ComplexMatrix schur_mat; - ComplexMatrix unitary_mat; - - select_function selector; - - octave_idx_type init (const ComplexMatrix& a, const std::string& ord, - bool calc_unitary); -}; - -#endif diff -r f780d057a3ec -r e69eaee28737 liboctave/numeric/dbleSCHUR.cc --- a/liboctave/numeric/dbleSCHUR.cc Thu Jan 14 19:59:52 2016 +1100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,166 +0,0 @@ -/* - -Copyright (C) 1994-2015 John W. Eaton - -This file is part of Octave. - -Octave is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3 of the License, or (at your -option) any later version. - -Octave is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with Octave; see the file COPYING. If not, see -. - -*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include - -#include "dbleSCHUR.h" -#include "f77-fcn.h" -#include "lo-error.h" - -extern "C" -{ - F77_RET_T - F77_FUNC (dgeesx, DGEESX) (F77_CONST_CHAR_ARG_DECL, - F77_CONST_CHAR_ARG_DECL, - SCHUR::select_function, - F77_CONST_CHAR_ARG_DECL, - const octave_idx_type&, double*, - const octave_idx_type&, octave_idx_type&, - double*, double*, double*, const octave_idx_type&, - double&, double&, double*, const octave_idx_type&, - octave_idx_type*, const octave_idx_type&, - octave_idx_type*, octave_idx_type& - F77_CHAR_ARG_LEN_DECL - F77_CHAR_ARG_LEN_DECL - F77_CHAR_ARG_LEN_DECL); -} - -static octave_idx_type -select_ana (const double& a, const double&) -{ - return (a < 0.0); -} - -static octave_idx_type -select_dig (const double& a, const double& b) -{ - return (hypot (a, b) < 1.0); -} - -octave_idx_type -SCHUR::init (const Matrix& a, const std::string& ord, bool calc_unitary) -{ - octave_idx_type a_nr = a.rows (); - octave_idx_type a_nc = a.cols (); - - if (a_nr != a_nc) - (*current_liboctave_error_handler) ("SCHUR requires square matrix"); - - if (a_nr == 0) - { - schur_mat.clear (); - unitary_mat.clear (); - return 0; - } - - // Workspace requirements may need to be fixed if any of the - // following change. - - char jobvs; - char sense = 'N'; - char sort = 'N'; - - if (calc_unitary) - jobvs = 'V'; - else - jobvs = 'N'; - - char ord_char = ord.empty () ? 'U' : ord[0]; - - if (ord_char == 'A' || ord_char == 'D' || ord_char == 'a' || ord_char == 'd') - sort = 'S'; - - if (ord_char == 'A' || ord_char == 'a') - selector = select_ana; - else if (ord_char == 'D' || ord_char == 'd') - selector = select_dig; - else - selector = 0; - - octave_idx_type n = a_nc; - octave_idx_type lwork = 8 * n; - octave_idx_type liwork = 1; - octave_idx_type info; - octave_idx_type sdim; - double rconde; - double rcondv; - - schur_mat = a; - - if (calc_unitary) - unitary_mat.clear (n, n); - - double *s = schur_mat.fortran_vec (); - double *q = unitary_mat.fortran_vec (); - - Array wr (dim_vector (n, 1)); - double *pwr = wr.fortran_vec (); - - Array wi (dim_vector (n, 1)); - double *pwi = wi.fortran_vec (); - - Array work (dim_vector (lwork, 1)); - double *pwork = work.fortran_vec (); - - // BWORK is not referenced for the non-ordered Schur routine. - octave_idx_type ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n; - Array bwork (dim_vector (ntmp, 1)); - octave_idx_type *pbwork = bwork.fortran_vec (); - - Array iwork (dim_vector (liwork, 1)); - octave_idx_type *piwork = iwork.fortran_vec (); - - F77_XFCN (dgeesx, DGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1), - F77_CONST_CHAR_ARG2 (&sort, 1), - selector, - F77_CONST_CHAR_ARG2 (&sense, 1), - n, s, n, sdim, pwr, pwi, q, n, rconde, rcondv, - pwork, lwork, piwork, liwork, pbwork, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); - - return info; -} - -std::ostream& -operator << (std::ostream& os, const SCHUR& a) -{ - os << a.schur_matrix () << "\n"; - os << a.unitary_matrix () << "\n"; - - return os; -} - -SCHUR::SCHUR (const Matrix& s, const Matrix& u) - : schur_mat (s), unitary_mat (u), selector (0) -{ - octave_idx_type n = s.rows (); - if (s.columns () != n || u.rows () != n || u.columns () != n) - (*current_liboctave_error_handler) - ("schur: inconsistent matrix dimensions"); -} - diff -r f780d057a3ec -r e69eaee28737 liboctave/numeric/dbleSCHUR.h --- a/liboctave/numeric/dbleSCHUR.h Thu Jan 14 19:59:52 2016 +1100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -/* - -Copyright (C) 1994-2015 John W. Eaton - -This file is part of Octave. - -Octave is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3 of the License, or (at your -option) any later version. - -Octave is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with Octave; see the file COPYING. If not, see -. - -*/ - -#if ! defined (octave_dbleSCHUR_h) -#define octave_dbleSCHUR_h 1 - -#include "octave-config.h" - -#include -#include - -#include "dMatrix.h" - -class -OCTAVE_API -SCHUR -{ -public: - - SCHUR (void) : schur_mat (), unitary_mat (), selector (0) { } - - SCHUR (const Matrix& a, const std::string& ord, bool calc_unitary = true) - : schur_mat (), unitary_mat (), selector (0) - { - init (a, ord, calc_unitary); - } - - SCHUR (const Matrix& a, const std::string& ord, int& info, - bool calc_unitary = true) - : schur_mat (), unitary_mat (), selector (0) - { - info = init (a, ord, calc_unitary); - } - - SCHUR (const SCHUR& a) - : schur_mat (a.schur_mat), unitary_mat (a.unitary_mat), selector (0) - { } - - SCHUR (const Matrix& s, const Matrix& u); - - SCHUR& operator = (const SCHUR& a) - { - if (this != &a) - { - schur_mat = a.schur_mat; - unitary_mat = a.unitary_mat; - } - return *this; - } - - ~SCHUR (void) { } - - Matrix schur_matrix (void) const { return schur_mat; } - - Matrix unitary_matrix (void) const { return unitary_mat; } - - friend std::ostream& operator << (std::ostream& os, const SCHUR& a); - - typedef octave_idx_type (*select_function) (const double&, const double&); - -private: - - Matrix schur_mat; - Matrix unitary_mat; - - select_function selector; - - octave_idx_type init (const Matrix& a, const std::string& ord, - bool calc_unitary); -}; - -#endif diff -r f780d057a3ec -r e69eaee28737 liboctave/numeric/fCmplxSCHUR.cc --- a/liboctave/numeric/fCmplxSCHUR.cc Thu Jan 14 19:59:52 2016 +1100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,171 +0,0 @@ -/* - -Copyright (C) 1994-2015 John W. Eaton - -This file is part of Octave. - -Octave is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3 of the License, or (at your -option) any later version. - -Octave is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with Octave; see the file COPYING. If not, see -. - -*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "fCmplxSCHUR.h" -#include "f77-fcn.h" -#include "lo-error.h" -#include "oct-locbuf.h" - -extern "C" -{ - F77_RET_T - F77_FUNC (cgeesx, CGEESX) (F77_CONST_CHAR_ARG_DECL, - F77_CONST_CHAR_ARG_DECL, - FloatComplexSCHUR::select_function, - F77_CONST_CHAR_ARG_DECL, - const octave_idx_type&, FloatComplex*, - const octave_idx_type&, octave_idx_type&, - FloatComplex*, FloatComplex*, - const octave_idx_type&, float&, float&, - FloatComplex*, const octave_idx_type&, - float*, octave_idx_type*, octave_idx_type& - F77_CHAR_ARG_LEN_DECL - F77_CHAR_ARG_LEN_DECL - F77_CHAR_ARG_LEN_DECL); - F77_RET_T - F77_FUNC (crsf2csf, CRSF2CSF) (const octave_idx_type&, FloatComplex *, - FloatComplex *, float *, float *); -} - -static octave_idx_type -select_ana (const FloatComplex& a) -{ - return a.real () < 0.0; -} - -static octave_idx_type -select_dig (const FloatComplex& a) -{ - return (abs (a) < 1.0); -} - -octave_idx_type -FloatComplexSCHUR::init (const FloatComplexMatrix& a, const std::string& ord, - bool calc_unitary) -{ - octave_idx_type a_nr = a.rows (); - octave_idx_type a_nc = a.cols (); - - if (a_nr != a_nc) - (*current_liboctave_error_handler) - ("FloatComplexSCHUR requires square matrix"); - - if (a_nr == 0) - { - schur_mat.clear (); - unitary_mat.clear (); - return 0; - } - - // Workspace requirements may need to be fixed if any of the - // following change. - - char jobvs; - char sense = 'N'; - char sort = 'N'; - - if (calc_unitary) - jobvs = 'V'; - else - jobvs = 'N'; - - char ord_char = ord.empty () ? 'U' : ord[0]; - - if (ord_char == 'A' || ord_char == 'D' || ord_char == 'a' || ord_char == 'd') - sort = 'S'; - - if (ord_char == 'A' || ord_char == 'a') - selector = select_ana; - else if (ord_char == 'D' || ord_char == 'd') - selector = select_dig; - else - selector = 0; - - octave_idx_type n = a_nc; - octave_idx_type lwork = 8 * n; - octave_idx_type info; - octave_idx_type sdim; - float rconde; - float rcondv; - - schur_mat = a; - if (calc_unitary) - unitary_mat.clear (n, n); - - FloatComplex *s = schur_mat.fortran_vec (); - FloatComplex *q = unitary_mat.fortran_vec (); - - Array rwork (dim_vector (n, 1)); - float *prwork = rwork.fortran_vec (); - - Array w (dim_vector (n, 1)); - FloatComplex *pw = w.fortran_vec (); - - Array work (dim_vector (lwork, 1)); - FloatComplex *pwork = work.fortran_vec (); - - // BWORK is not referenced for non-ordered Schur. - octave_idx_type ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n; - Array bwork (dim_vector (ntmp, 1)); - octave_idx_type *pbwork = bwork.fortran_vec (); - - F77_XFCN (cgeesx, CGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1), - F77_CONST_CHAR_ARG2 (&sort, 1), - selector, - F77_CONST_CHAR_ARG2 (&sense, 1), - n, s, n, sdim, pw, q, n, rconde, rcondv, - pwork, lwork, prwork, pbwork, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); - - return info; -} - -FloatComplexSCHUR::FloatComplexSCHUR (const FloatComplexMatrix& s, - const FloatComplexMatrix& u) - : schur_mat (s), unitary_mat (u), selector (0) -{ - octave_idx_type n = s.rows (); - if (s.columns () != n || u.rows () != n || u.columns () != n) - (*current_liboctave_error_handler) - ("schur: inconsistent matrix dimensions"); -} - -FloatComplexSCHUR::FloatComplexSCHUR (const FloatSCHUR& s) - : schur_mat (s.schur_matrix ()), unitary_mat (s.unitary_matrix ()), - selector (0) -{ - octave_idx_type n = schur_mat.rows (); - if (n > 0) - { - OCTAVE_LOCAL_BUFFER (float, c, n-1); - OCTAVE_LOCAL_BUFFER (float, sx, n-1); - - F77_XFCN (crsf2csf, CRSF2CSF, (n, schur_mat.fortran_vec (), - unitary_mat.fortran_vec (), c, sx)); - } -} diff -r f780d057a3ec -r e69eaee28737 liboctave/numeric/fCmplxSCHUR.h --- a/liboctave/numeric/fCmplxSCHUR.h Thu Jan 14 19:59:52 2016 +1100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/* - -Copyright (C) 1994-2015 John W. Eaton - -This file is part of Octave. - -Octave is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3 of the License, or (at your -option) any later version. - -Octave is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with Octave; see the file COPYING. If not, see -. - -*/ - -#if ! defined (octave_fCmplxSCHUR_h) -#define octave_fCmplxSCHUR_h 1 - -#include "octave-config.h" - -#include -#include - -#include "fCMatrix.h" -#include "floatSCHUR.h" - -class -OCTAVE_API -FloatComplexSCHUR -{ -public: - - FloatComplexSCHUR (void) : schur_mat (), unitary_mat (), selector (0) { } - - FloatComplexSCHUR (const FloatComplexMatrix& a, const std::string& ord, - bool calc_unitary = true) - : schur_mat (), unitary_mat (), selector (0) - { - init (a, ord, calc_unitary); - } - - FloatComplexSCHUR (const FloatComplexMatrix& a, const std::string& ord, - octave_idx_type& info, bool calc_unitary = true) - : schur_mat (), unitary_mat (), selector (0) - { - info = init (a, ord, calc_unitary); - } - - FloatComplexSCHUR (const FloatComplexSCHUR& a) - : schur_mat (a.schur_mat), unitary_mat (a.unitary_mat), selector (0) - { } - - FloatComplexSCHUR (const FloatComplexMatrix& s, const FloatComplexMatrix& u); - - FloatComplexSCHUR (const FloatSCHUR& s); - - FloatComplexSCHUR& operator = (const FloatComplexSCHUR& a) - { - if (this != &a) - { - schur_mat = a.schur_mat; - unitary_mat = a.unitary_mat; - } - return *this; - } - - ~FloatComplexSCHUR (void) { } - - FloatComplexMatrix schur_matrix (void) const { return schur_mat; } - - FloatComplexMatrix unitary_matrix (void) const { return unitary_mat; } - - friend std::ostream& operator << (std::ostream& os, - const FloatComplexSCHUR& a); - - typedef octave_idx_type (*select_function) (const FloatComplex&); - -private: - - FloatComplexMatrix schur_mat; - FloatComplexMatrix unitary_mat; - - select_function selector; - - octave_idx_type init (const FloatComplexMatrix& a, const std::string& ord, - bool calc_unitary); -}; - -#endif diff -r f780d057a3ec -r e69eaee28737 liboctave/numeric/floatSCHUR.cc --- a/liboctave/numeric/floatSCHUR.cc Thu Jan 14 19:59:52 2016 +1100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,166 +0,0 @@ -/* - -Copyright (C) 1994-2015 John W. Eaton - -This file is part of Octave. - -Octave is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3 of the License, or (at your -option) any later version. - -Octave is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with Octave; see the file COPYING. If not, see -. - -*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include - -#include "floatSCHUR.h" -#include "f77-fcn.h" -#include "lo-error.h" - -extern "C" -{ - F77_RET_T - F77_FUNC (sgeesx, SGEESX) (F77_CONST_CHAR_ARG_DECL, - F77_CONST_CHAR_ARG_DECL, - FloatSCHUR::select_function, - F77_CONST_CHAR_ARG_DECL, - const octave_idx_type&, float*, - const octave_idx_type&, octave_idx_type&, - float*, float*, float*, const octave_idx_type&, - float&, float&, float*, const octave_idx_type&, - octave_idx_type*, const octave_idx_type&, - octave_idx_type*, octave_idx_type& - F77_CHAR_ARG_LEN_DECL - F77_CHAR_ARG_LEN_DECL - F77_CHAR_ARG_LEN_DECL); -} - -static octave_idx_type -select_ana (const float& a, const float&) -{ - return (a < 0.0); -} - -static octave_idx_type -select_dig (const float& a, const float& b) -{ - return (hypot (a, b) < 1.0); -} - -octave_idx_type -FloatSCHUR::init (const FloatMatrix& a, const std::string& ord, - bool calc_unitary) -{ - octave_idx_type a_nr = a.rows (); - octave_idx_type a_nc = a.cols (); - - if (a_nr != a_nc) - (*current_liboctave_error_handler) ("FloatSCHUR requires square matrix"); - - if (a_nr == 0) - { - schur_mat.clear (); - unitary_mat.clear (); - return 0; - } - - // Workspace requirements may need to be fixed if any of the - // following change. - - char jobvs; - char sense = 'N'; - char sort = 'N'; - - if (calc_unitary) - jobvs = 'V'; - else - jobvs = 'N'; - - char ord_char = ord.empty () ? 'U' : ord[0]; - - if (ord_char == 'A' || ord_char == 'D' || ord_char == 'a' || ord_char == 'd') - sort = 'S'; - - if (ord_char == 'A' || ord_char == 'a') - selector = select_ana; - else if (ord_char == 'D' || ord_char == 'd') - selector = select_dig; - else - selector = 0; - - octave_idx_type n = a_nc; - octave_idx_type lwork = 8 * n; - octave_idx_type liwork = 1; - octave_idx_type info; - octave_idx_type sdim; - float rconde; - float rcondv; - - schur_mat = a; - - if (calc_unitary) - unitary_mat.clear (n, n); - - float *s = schur_mat.fortran_vec (); - float *q = unitary_mat.fortran_vec (); - - Array wr (dim_vector (n, 1)); - float *pwr = wr.fortran_vec (); - - Array wi (dim_vector (n, 1)); - float *pwi = wi.fortran_vec (); - - Array work (dim_vector (lwork, 1)); - float *pwork = work.fortran_vec (); - - // BWORK is not referenced for the non-ordered Schur routine. - octave_idx_type ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n; - Array bwork (dim_vector (ntmp, 1)); - octave_idx_type *pbwork = bwork.fortran_vec (); - - Array iwork (dim_vector (liwork, 1)); - octave_idx_type *piwork = iwork.fortran_vec (); - - F77_XFCN (sgeesx, SGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1), - F77_CONST_CHAR_ARG2 (&sort, 1), - selector, - F77_CONST_CHAR_ARG2 (&sense, 1), - n, s, n, sdim, pwr, pwi, q, n, rconde, rcondv, - pwork, lwork, piwork, liwork, pbwork, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); - - return info; -} - -FloatSCHUR::FloatSCHUR (const FloatMatrix& s, const FloatMatrix& u) - : schur_mat (s), unitary_mat (u), selector (0) -{ - octave_idx_type n = s.rows (); - if (s.columns () != n || u.rows () != n || u.columns () != n) - (*current_liboctave_error_handler) - ("schur: inconsistent matrix dimensions"); -} - -std::ostream& -operator << (std::ostream& os, const FloatSCHUR& a) -{ - os << a.schur_matrix () << "\n"; - os << a.unitary_matrix () << "\n"; - - return os; -} diff -r f780d057a3ec -r e69eaee28737 liboctave/numeric/floatSCHUR.h --- a/liboctave/numeric/floatSCHUR.h Thu Jan 14 19:59:52 2016 +1100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/* - -Copyright (C) 1994-2015 John W. Eaton - -This file is part of Octave. - -Octave is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3 of the License, or (at your -option) any later version. - -Octave is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with Octave; see the file COPYING. If not, see -. - -*/ - -#if ! defined (octave_floatSCHUR_h) -#define octave_floatSCHUR_h 1 - -#include "octave-config.h" - -#include -#include - -#include "fMatrix.h" - -class -OCTAVE_API -FloatSCHUR -{ -public: - - FloatSCHUR (void) : schur_mat (), unitary_mat (), selector (0) { } - - FloatSCHUR (const FloatMatrix& a, const std::string& ord, - bool calc_unitary = true) - : schur_mat (), unitary_mat (), selector (0) - { - init (a, ord, calc_unitary); - } - - FloatSCHUR (const FloatMatrix& a, const std::string& ord, int& info, - bool calc_unitary = true) - : schur_mat (), unitary_mat (), selector (0) - { - info = init (a, ord, calc_unitary); - } - - FloatSCHUR (const FloatSCHUR& a) - : schur_mat (a.schur_mat), unitary_mat (a.unitary_mat), selector (0) - { } - - FloatSCHUR (const FloatMatrix& s, const FloatMatrix& u); - - FloatSCHUR& operator = (const FloatSCHUR& a) - { - if (this != &a) - { - schur_mat = a.schur_mat; - unitary_mat = a.unitary_mat; - } - return *this; - } - - ~FloatSCHUR (void) { } - - FloatMatrix schur_matrix (void) const { return schur_mat; } - - FloatMatrix unitary_matrix (void) const { return unitary_mat; } - - friend std::ostream& operator << (std::ostream& os, const FloatSCHUR& a); - - typedef octave_idx_type (*select_function) (const float&, const float&); - -private: - - FloatMatrix schur_mat; - FloatMatrix unitary_mat; - - select_function selector; - - octave_idx_type init (const FloatMatrix& a, const std::string& ord, - bool calc_unitary); -}; - -#endif diff -r f780d057a3ec -r e69eaee28737 liboctave/numeric/module.mk --- a/liboctave/numeric/module.mk Thu Jan 14 19:59:52 2016 +1100 +++ b/liboctave/numeric/module.mk Mon Feb 15 20:06:12 2016 -0500 @@ -15,7 +15,6 @@ liboctave/numeric/CmplxLU.h \ liboctave/numeric/CmplxQR.h \ liboctave/numeric/CmplxQRP.h \ - liboctave/numeric/CmplxSCHUR.h \ liboctave/numeric/CmplxSVD.h \ liboctave/numeric/CollocWt.h \ liboctave/numeric/DAE.h \ @@ -48,7 +47,6 @@ liboctave/numeric/dbleLU.h \ liboctave/numeric/dbleQR.h \ liboctave/numeric/dbleQRP.h \ - liboctave/numeric/dbleSCHUR.h \ liboctave/numeric/dbleSVD.h \ liboctave/numeric/eigs-base.h \ liboctave/numeric/fCmplxAEPBAL.h \ @@ -58,7 +56,6 @@ liboctave/numeric/fCmplxLU.h \ liboctave/numeric/fCmplxQR.h \ liboctave/numeric/fCmplxQRP.h \ - liboctave/numeric/fCmplxSCHUR.h \ liboctave/numeric/fCmplxSVD.h \ liboctave/numeric/fEIG.h \ liboctave/numeric/floatAEPBAL.h \ @@ -68,7 +65,6 @@ liboctave/numeric/floatLU.h \ liboctave/numeric/floatQR.h \ liboctave/numeric/floatQRP.h \ - liboctave/numeric/floatSCHUR.h \ liboctave/numeric/floatSVD.h \ liboctave/numeric/lo-mappers.h \ liboctave/numeric/lo-specfun.h \ @@ -80,6 +76,7 @@ liboctave/numeric/randgamma.h \ liboctave/numeric/randmtzig.h \ liboctave/numeric/randpoisson.h \ + liboctave/numeric/schur.h \ liboctave/numeric/sparse-chol.h \ liboctave/numeric/sparse-dmsolve.h \ liboctave/numeric/sparse-lu.h \ @@ -98,7 +95,6 @@ liboctave/numeric/CmplxLU.cc \ liboctave/numeric/CmplxQR.cc \ liboctave/numeric/CmplxQRP.cc \ - liboctave/numeric/CmplxSCHUR.cc \ liboctave/numeric/CmplxSVD.cc \ liboctave/numeric/CollocWt.cc \ liboctave/numeric/DASPK.cc \ @@ -115,7 +111,6 @@ liboctave/numeric/dbleLU.cc \ liboctave/numeric/dbleQR.cc \ liboctave/numeric/dbleQRP.cc \ - liboctave/numeric/dbleSCHUR.cc \ liboctave/numeric/dbleSVD.cc \ liboctave/numeric/eigs-base.cc \ liboctave/numeric/fCmplxAEPBAL.cc \ @@ -125,7 +120,6 @@ liboctave/numeric/fCmplxLU.cc \ liboctave/numeric/fCmplxQR.cc \ liboctave/numeric/fCmplxQRP.cc \ - liboctave/numeric/fCmplxSCHUR.cc \ liboctave/numeric/fCmplxSVD.cc \ liboctave/numeric/fEIG.cc \ liboctave/numeric/floatAEPBAL.cc \ @@ -135,7 +129,6 @@ liboctave/numeric/floatLU.cc \ liboctave/numeric/floatQR.cc \ liboctave/numeric/floatQRP.cc \ - liboctave/numeric/floatSCHUR.cc \ liboctave/numeric/floatSVD.cc \ liboctave/numeric/lo-mappers.cc \ liboctave/numeric/lo-specfun.cc \ @@ -144,6 +137,7 @@ liboctave/numeric/oct-norm.cc \ liboctave/numeric/oct-rand.cc \ liboctave/numeric/oct-spparms.cc \ + liboctave/numeric/schur.cc \ liboctave/numeric/sparse-chol.cc \ liboctave/numeric/sparse-dmsolve.cc \ liboctave/numeric/sparse-lu.cc \ diff -r f780d057a3ec -r e69eaee28737 liboctave/numeric/schur.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liboctave/numeric/schur.cc Mon Feb 15 20:06:12 2016 -0500 @@ -0,0 +1,573 @@ +/* + +Copyright (C) 1994-2015 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +. + +*/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "CMatrix.h" +#include "dMatrix.h" +#include "f77-fcn.h" +#include "fCMatrix.h" +#include "fMatrix.h" +#include "lo-error.h" +#include "schur.h" + +typedef octave_idx_type (*double_selector) (const double&, const double&); +typedef octave_idx_type (*float_selector) (const float&, const float&); +typedef octave_idx_type (*complex_selector) (const Complex&); +typedef octave_idx_type (*float_complex_selector) (const FloatComplex&); + +extern "C" +{ + F77_RET_T + F77_FUNC (dgeesx, DGEESX) (F77_CONST_CHAR_ARG_DECL, + F77_CONST_CHAR_ARG_DECL, + double_selector, + F77_CONST_CHAR_ARG_DECL, + const octave_idx_type&, double*, + const octave_idx_type&, octave_idx_type&, + double*, double*, double*, const octave_idx_type&, + double&, double&, double*, const octave_idx_type&, + octave_idx_type*, const octave_idx_type&, + octave_idx_type*, octave_idx_type& + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL); + + F77_RET_T + F77_FUNC (sgeesx, SGEESX) (F77_CONST_CHAR_ARG_DECL, + F77_CONST_CHAR_ARG_DECL, + float_selector, + F77_CONST_CHAR_ARG_DECL, + const octave_idx_type&, float*, + const octave_idx_type&, octave_idx_type&, + float*, float*, float*, const octave_idx_type&, + float&, float&, float*, const octave_idx_type&, + octave_idx_type*, const octave_idx_type&, + octave_idx_type*, octave_idx_type& + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL); + + F77_RET_T + F77_FUNC (zgeesx, ZGEESX) (F77_CONST_CHAR_ARG_DECL, + F77_CONST_CHAR_ARG_DECL, + complex_selector, + F77_CONST_CHAR_ARG_DECL, + const octave_idx_type&, Complex*, + const octave_idx_type&, octave_idx_type&, + Complex*, Complex*, const octave_idx_type&, + double&, double&, Complex*, + const octave_idx_type&, double*, + octave_idx_type*, octave_idx_type& + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL); + + F77_RET_T + F77_FUNC (zrsf2csf, ZRSF2CSF) (const octave_idx_type&, Complex *, + Complex *, double *, double *); + F77_RET_T + F77_FUNC (cgeesx, CGEESX) (F77_CONST_CHAR_ARG_DECL, + F77_CONST_CHAR_ARG_DECL, + float_complex_selector, + F77_CONST_CHAR_ARG_DECL, + const octave_idx_type&, FloatComplex*, + const octave_idx_type&, octave_idx_type&, + FloatComplex*, FloatComplex*, + const octave_idx_type&, float&, float&, + FloatComplex*, const octave_idx_type&, + float*, octave_idx_type*, octave_idx_type& + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL); + + F77_RET_T + F77_FUNC (crsf2csf, CRSF2CSF) (const octave_idx_type&, FloatComplex *, + FloatComplex *, float *, float *); +} + +// For real types. + +template +static octave_idx_type +select_ana (const T& a, const T&) +{ + return (a < 0.0); +} + +template +static octave_idx_type +select_dig (const T& a, const T& b) +{ + return (hypot (a, b) < 1.0); +} + +// For complex types. + +template +static octave_idx_type +select_ana (const T& a) +{ + return a.real () < 0.0; +} + +template +static octave_idx_type +select_dig (const T& a) +{ + return (abs (a) < 1.0); +} + +template <> +octave_idx_type +schur::init (const Matrix& a, const std::string& ord, bool calc_unitary) +{ + octave_idx_type a_nr = a.rows (); + octave_idx_type a_nc = a.cols (); + + if (a_nr != a_nc) + (*current_liboctave_error_handler) ("schur: requires square matrix"); + + if (a_nr == 0) + { + schur_mat.clear (); + unitary_mat.clear (); + return 0; + } + + // Workspace requirements may need to be fixed if any of the + // following change. + + char jobvs; + char sense = 'N'; + char sort = 'N'; + + if (calc_unitary) + jobvs = 'V'; + else + jobvs = 'N'; + + char ord_char = ord.empty () ? 'U' : ord[0]; + + if (ord_char == 'A' || ord_char == 'D' || ord_char == 'a' || ord_char == 'd') + sort = 'S'; + + double_selector selector = 0; + if (ord_char == 'A' || ord_char == 'a') + selector = select_ana; + else if (ord_char == 'D' || ord_char == 'd') + selector = select_dig; + else + selector = 0; + + octave_idx_type n = a_nc; + octave_idx_type lwork = 8 * n; + octave_idx_type liwork = 1; + octave_idx_type info; + octave_idx_type sdim; + double rconde; + double rcondv; + + schur_mat = a; + + if (calc_unitary) + unitary_mat.clear (n, n); + + double *s = schur_mat.fortran_vec (); + double *q = unitary_mat.fortran_vec (); + + Array wr (dim_vector (n, 1)); + double *pwr = wr.fortran_vec (); + + Array wi (dim_vector (n, 1)); + double *pwi = wi.fortran_vec (); + + Array work (dim_vector (lwork, 1)); + double *pwork = work.fortran_vec (); + + // BWORK is not referenced for the non-ordered Schur routine. + octave_idx_type ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n; + Array bwork (dim_vector (ntmp, 1)); + octave_idx_type *pbwork = bwork.fortran_vec (); + + Array iwork (dim_vector (liwork, 1)); + octave_idx_type *piwork = iwork.fortran_vec (); + + F77_XFCN (dgeesx, DGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1), + F77_CONST_CHAR_ARG2 (&sort, 1), + selector, + F77_CONST_CHAR_ARG2 (&sense, 1), + n, s, n, sdim, pwr, pwi, q, n, rconde, rcondv, + pwork, lwork, piwork, liwork, pbwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); + + return info; +} + +template <> +octave_idx_type +schur::init (const FloatMatrix& a, const std::string& ord, + bool calc_unitary) +{ + octave_idx_type a_nr = a.rows (); + octave_idx_type a_nc = a.cols (); + + if (a_nr != a_nc) + (*current_liboctave_error_handler) ("SCHUR requires square matrix"); + + if (a_nr == 0) + { + schur_mat.clear (); + unitary_mat.clear (); + return 0; + } + + // Workspace requirements may need to be fixed if any of the + // following change. + + char jobvs; + char sense = 'N'; + char sort = 'N'; + + if (calc_unitary) + jobvs = 'V'; + else + jobvs = 'N'; + + char ord_char = ord.empty () ? 'U' : ord[0]; + + if (ord_char == 'A' || ord_char == 'D' || ord_char == 'a' || ord_char == 'd') + sort = 'S'; + + float_selector selector = 0; + if (ord_char == 'A' || ord_char == 'a') + selector = select_ana; + else if (ord_char == 'D' || ord_char == 'd') + selector = select_dig; + else + selector = 0; + + octave_idx_type n = a_nc; + octave_idx_type lwork = 8 * n; + octave_idx_type liwork = 1; + octave_idx_type info; + octave_idx_type sdim; + float rconde; + float rcondv; + + schur_mat = a; + + if (calc_unitary) + unitary_mat.clear (n, n); + + float *s = schur_mat.fortran_vec (); + float *q = unitary_mat.fortran_vec (); + + Array wr (dim_vector (n, 1)); + float *pwr = wr.fortran_vec (); + + Array wi (dim_vector (n, 1)); + float *pwi = wi.fortran_vec (); + + Array work (dim_vector (lwork, 1)); + float *pwork = work.fortran_vec (); + + // BWORK is not referenced for the non-ordered Schur routine. + octave_idx_type ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n; + Array bwork (dim_vector (ntmp, 1)); + octave_idx_type *pbwork = bwork.fortran_vec (); + + Array iwork (dim_vector (liwork, 1)); + octave_idx_type *piwork = iwork.fortran_vec (); + + F77_XFCN (sgeesx, SGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1), + F77_CONST_CHAR_ARG2 (&sort, 1), + selector, + F77_CONST_CHAR_ARG2 (&sense, 1), + n, s, n, sdim, pwr, pwi, q, n, rconde, rcondv, + pwork, lwork, piwork, liwork, pbwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); + + return info; +} + +template <> +octave_idx_type +schur::init (const ComplexMatrix& a, const std::string& ord, + bool calc_unitary) +{ + octave_idx_type a_nr = a.rows (); + octave_idx_type a_nc = a.cols (); + + if (a_nr != a_nc) + (*current_liboctave_error_handler) ("SCHUR requires square matrix"); + + if (a_nr == 0) + { + schur_mat.clear (); + unitary_mat.clear (); + return 0; + } + + // Workspace requirements may need to be fixed if any of the + // following change. + + char jobvs; + char sense = 'N'; + char sort = 'N'; + + if (calc_unitary) + jobvs = 'V'; + else + jobvs = 'N'; + + char ord_char = ord.empty () ? 'U' : ord[0]; + + if (ord_char == 'A' || ord_char == 'D' || ord_char == 'a' || ord_char == 'd') + sort = 'S'; + + complex_selector selector = 0; + if (ord_char == 'A' || ord_char == 'a') + selector = select_ana; + else if (ord_char == 'D' || ord_char == 'd') + selector = select_dig; + else + selector = 0; + + octave_idx_type n = a_nc; + octave_idx_type lwork = 8 * n; + octave_idx_type info; + octave_idx_type sdim; + double rconde; + double rcondv; + + schur_mat = a; + if (calc_unitary) + unitary_mat.clear (n, n); + + Complex *s = schur_mat.fortran_vec (); + Complex *q = unitary_mat.fortran_vec (); + + Array rwork (dim_vector (n, 1)); + double *prwork = rwork.fortran_vec (); + + Array w (dim_vector (n, 1)); + Complex *pw = w.fortran_vec (); + + Array work (dim_vector (lwork, 1)); + Complex *pwork = work.fortran_vec (); + + // BWORK is not referenced for non-ordered Schur. + octave_idx_type ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n; + Array bwork (dim_vector (ntmp, 1)); + octave_idx_type *pbwork = bwork.fortran_vec (); + + F77_XFCN (zgeesx, ZGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1), + F77_CONST_CHAR_ARG2 (&sort, 1), + selector, + F77_CONST_CHAR_ARG2 (&sense, 1), + n, s, n, sdim, pw, q, n, rconde, rcondv, + pwork, lwork, prwork, pbwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); + + return info; +} + +template <> +schur +rsf2csf (const Matrix& s_arg, const Matrix& u_arg) +{ + ComplexMatrix s (s_arg); + ComplexMatrix u (u_arg); + + octave_idx_type n = s.rows (); + + if (s.columns () != n || u.rows () != n || u.columns () != n) + (*current_liboctave_error_handler) + ("rsf2csf: inconsistent matrix dimensions"); + + if (n > 0) + { + OCTAVE_LOCAL_BUFFER (double, c, n-1); + OCTAVE_LOCAL_BUFFER (double, sx, n-1); + + F77_XFCN (zrsf2csf, ZRSF2CSF, (n, s.fortran_vec (), + u.fortran_vec (), c, sx)); + } + + return schur (s, u); +} + +template <> +octave_idx_type +schur::init (const FloatComplexMatrix& a, + const std::string& ord, bool calc_unitary) +{ + octave_idx_type a_nr = a.rows (); + octave_idx_type a_nc = a.cols (); + + if (a_nr != a_nc) + (*current_liboctave_error_handler) ("SCHUR requires square matrix"); + + if (a_nr == 0) + { + schur_mat.clear (); + unitary_mat.clear (); + return 0; + } + + // Workspace requirements may need to be fixed if any of the + // following change. + + char jobvs; + char sense = 'N'; + char sort = 'N'; + + if (calc_unitary) + jobvs = 'V'; + else + jobvs = 'N'; + + char ord_char = ord.empty () ? 'U' : ord[0]; + + if (ord_char == 'A' || ord_char == 'D' || ord_char == 'a' || ord_char == 'd') + sort = 'S'; + + float_complex_selector selector = 0; + if (ord_char == 'A' || ord_char == 'a') + selector = select_ana; + else if (ord_char == 'D' || ord_char == 'd') + selector = select_dig; + else + selector = 0; + + octave_idx_type n = a_nc; + octave_idx_type lwork = 8 * n; + octave_idx_type info; + octave_idx_type sdim; + float rconde; + float rcondv; + + schur_mat = a; + if (calc_unitary) + unitary_mat.clear (n, n); + + FloatComplex *s = schur_mat.fortran_vec (); + FloatComplex *q = unitary_mat.fortran_vec (); + + Array rwork (dim_vector (n, 1)); + float *prwork = rwork.fortran_vec (); + + Array w (dim_vector (n, 1)); + FloatComplex *pw = w.fortran_vec (); + + Array work (dim_vector (lwork, 1)); + FloatComplex *pwork = work.fortran_vec (); + + // BWORK is not referenced for non-ordered Schur. + octave_idx_type ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n; + Array bwork (dim_vector (ntmp, 1)); + octave_idx_type *pbwork = bwork.fortran_vec (); + + F77_XFCN (cgeesx, CGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1), + F77_CONST_CHAR_ARG2 (&sort, 1), + selector, + F77_CONST_CHAR_ARG2 (&sense, 1), + n, s, n, sdim, pw, q, n, rconde, rcondv, + pwork, lwork, prwork, pbwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); + + return info; +} + +template <> +schur +rsf2csf (const FloatMatrix& s_arg, const FloatMatrix& u_arg) +{ + FloatComplexMatrix s (s_arg); + FloatComplexMatrix u (u_arg); + + octave_idx_type n = s.rows (); + + if (s.columns () != n || u.rows () != n || u.columns () != n) + (*current_liboctave_error_handler) + ("rsf2csf: inconsistent matrix dimensions"); + + if (n > 0) + { + OCTAVE_LOCAL_BUFFER (float, c, n-1); + OCTAVE_LOCAL_BUFFER (float, sx, n-1); + + F77_XFCN (crsf2csf, CRSF2CSF, (n, s.fortran_vec (), + u.fortran_vec (), c, sx)); + } + + return schur (s, u); +} + +template +std::ostream& +operator << (std::ostream& os, const schur& a) +{ + os << a.schur_matrix () << "\n"; + os << a.unitary_matrix () << "\n"; + + return os; +} + +// Instantiations we need. + +template class schur; + +template class schur; + +template class schur; + +template class schur; + +template <> +std::ostream& +operator << (std::ostream& os, const schur& a); + +template <> +std::ostream& +operator << (std::ostream& os, const schur& a); + +template <> +std::ostream& +operator << (std::ostream& os, const schur& a); + +template <> +std::ostream& +operator << (std::ostream& os, const schur& a); diff -r f780d057a3ec -r e69eaee28737 liboctave/numeric/schur.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liboctave/numeric/schur.h Mon Feb 15 20:06:12 2016 -0500 @@ -0,0 +1,105 @@ +/* + +Copyright (C) 1994-2015 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +. + +*/ + +#if ! defined (octave_schur_h) +#define octave_schur_h 1 + +#include "octave-config.h" + +#include +#include + +#include "dMatrix.h" +#include "CMatrix.h" +#include "fMatrix.h" +#include "fCMatrix.h" + +template class schur; + +template +class +schur +{ +public: + + schur (void) : schur_mat (), unitary_mat () { } + + schur (const T& a, const std::string& ord, bool calc_unitary = true) + : schur_mat (), unitary_mat () + { + init (a, ord, calc_unitary); + } + + schur (const T& a, const std::string& ord, octave_idx_type& info, + bool calc_unitary = true) + : schur_mat (), unitary_mat () + { + info = init (a, ord, calc_unitary); + } + + // This one should really be protected or private but we need it in + // rsf2csf and I don't see how to make that function a friend of + // this class. + schur (const T& s, const T& u) : schur_mat (s), unitary_mat (u) { } + + schur (const schur& a) + + : schur_mat (a.schur_mat), unitary_mat (a.unitary_mat) + { } + + schur& operator = (const schur& a) + { + if (this != &a) + { + schur_mat = a.schur_mat; + unitary_mat = a.unitary_mat; + } + + return *this; + } + + ~schur (void) { } + + T schur_matrix (void) const { return schur_mat; } + + T unitary_matrix (void) const { return unitary_mat; } + +protected: + +private: + + T schur_mat; + T unitary_mat; + + octave_idx_type + init (const T& a, const std::string& ord, bool calc_unitary); +}; + +template +extern schur +rsf2csf (const AT& s, const AT& u); + +template +extern std::ostream& +operator << (std::ostream& os, const schur& a); + +#endif diff -r f780d057a3ec -r e69eaee28737 liboctave/operators/mx-defs.h --- a/liboctave/operators/mx-defs.h Thu Jan 14 19:59:52 2016 +1100 +++ b/liboctave/operators/mx-defs.h Mon Feb 15 20:06:12 2016 -0500 @@ -80,10 +80,7 @@ class FloatHESS; class FloatComplexHESS; -class SCHUR; -class ComplexSCHUR; -class FloatSCHUR; -class FloatComplexSCHUR; +template class schur; class SVD; class ComplexSVD; diff -r f780d057a3ec -r e69eaee28737 liboctave/operators/mx-ext.h --- a/liboctave/operators/mx-ext.h Thu Jan 14 19:59:52 2016 +1100 +++ b/liboctave/operators/mx-ext.h Mon Feb 15 20:06:12 2016 -0500 @@ -48,10 +48,7 @@ // Result of a Schur Decomposition -#include "dbleSCHUR.h" -#include "CmplxSCHUR.h" -#include "floatSCHUR.h" -#include "fCmplxSCHUR.h" +#include "schur.h" // Result of a Singular Value Decomposition.