hseqr.hpp

Go to the documentation of this file.
00001 /*
00002  * 
00003  * Copyright Jeremy Conlin 2008
00004  *
00005  * Distributed under the Boost Software License, Version 1.0.
00006  * (See accompanying file LICENSE_1_0.txt or copy at
00007  * http://www.boost.org/LICENSE_1_0.txt)
00008  *
00009  */
00010 
00011 #ifndef BOOST_NUMERIC_BINDINGS_LAPACK_HSEQR_HPP
00012 #define BOOST_NUMERIC_BINDINGS_LAPACK_HSEQR_HPP
00013 
00014 #include <iostream>
00015 #include <complex>
00016 #include <boost/numeric/bindings/traits/traits.hpp>
00017 #include <boost/numeric/bindings/traits/matrix_traits.hpp>
00018 #include <boost/numeric/bindings/traits/type_traits.hpp>
00019 #include <boost/numeric/bindings/lapack/lapack.h>
00020 #include <boost/numeric/bindings/lapack/workspace.hpp>
00021 #include <boost/numeric/bindings/traits/detail/array.hpp>
00022 
00023 #ifndef BOOST_NUMERIC_BINDINGS_NO_STRUCTURE_CHECK 
00024 #  include <boost/static_assert.hpp>
00025 #  include <boost/type_traits.hpp>
00026 #endif 
00027 
00028 
00029 namespace boost { namespace numeric { namespace bindings { 
00030 
00031   namespace lapack {
00032 
00034     //
00035     // Compute eigenvalues of an Hessenberg matrix, H.
00036     // 
00038 
00039     /* 
00040      * hseqr() computes the eigenvalues of a Hessenberg matrix H
00041      * and, optionally, the matrices T and Z from the Schur decomposition
00042      * H = Z U Z**T, where U is an upper quasi-triangular matrix (the
00043      * Schur form), and Z is the orthogonal matrix of Schur vectors.
00044      *
00045      * Optionally Z may be postmultiplied into an input orthogonal
00046      * matrix Q so that this routine can give the Schur factorization
00047      * of a matrix A which has been reduced to the Hessenberg form H
00048      * by the orthogonal matrix Q:  A = Q*H*Q**T = (QZ)*U*(QZ)**T.
00049      * 
00050      * There are two forms of the hseqr function:
00051      *
00052      * int hseqr( const char job, A& H, W& w)
00053      * int hseqr( const char job, const char compz, A& H, W& w, Z& z)
00054      *
00055      * The first form does not compute Schur vectors and is equivelant to
00056      * setting compz = 'N' in the second form.  hseqr returns a '0' if the
00057      * computation is successful.
00058      *
00059      * job.
00060      *   = 'E': compute eigenvalues only
00061      *   = 'S': compute eigenvalues and the Schur form U
00062      *
00063      * compz. (input)
00064      *   = 'N':  no Schur vectors are computed;  Equivalent to using the
00065      *           first form of the hseqr function.
00066      *   = 'I':  Z is initialized to the unit matrix and the matrix Z
00067      *           of Schur vectors of H is returned;
00068      *   = 'V':  Z must contain an orthogonal matrix Q on entry, and
00069      *           the product Q*Z is returned.
00070      * 
00071      * H is the Hessenberg matrix whose eigenpairs you're interested 
00072      * in. (input/output) On exit, if computation is successful and 
00073      * job = 'S', then H contains the
00074      * upper quasi-triangular matrix U from the Schur decomposition
00075      * (the Schur form); 2-by-2 diagonal blocks (corresponding to
00076      * complex conjugate pairs of eigenvalues) are returned in
00077      * standard form, with H(i,i) = H(i+1,i+1) and
00078      * H(i+1,i)*H(i,i+1) < 0. If computation is successful and 
00079      * job = 'E', the contents of H are unspecified on exit.  
00080      *
00081      * w (output) contains the computed eigenvalues of H which is the diagonal 
00082      * of U. Must be a complex object.
00083      *
00084      * Z. (input/output)
00085      * If compz = 'N', Z is not referenced.
00086      * If compz = 'I', on entry Z need not be set and on exit,
00087      * if computation is successful, Z contains the orthogonal matrix Z of the Schur
00088      * vectors of H.  If compz = 'V', on entry Z must contain an
00089      * N-by-N matrix Q, which is assumed to be equal to the unit
00090      * matrix . On exit, if computation is successful, Z contains Q*Z.
00091      *
00092      */ 
00093 
00094     namespace detail {
00095         // float
00096         inline
00097         int hseqr_backend(const char* job, const char* compz, const int* n, 
00098                 const int ilo, const int ihi, float* H, const int ldH, 
00099                 float* wr, float* wi, float* Z, const int ldz, float* work,
00100                 const int* lwork){
00101             int info;
00102 //          std::cout << "I'm inside lapack::detail::hseqr_backend for floats" 
00103 //              << std::endl;
00104             LAPACK_SHSEQR(job, compz, n, &ilo, &ihi, H, &ldH, wr, wi, 
00105                     Z, &ldz, work, lwork, &info);
00106             return info;
00107         }
00108 
00109         // double
00110         inline
00111         int hseqr_backend(const char* job, const char* compz, const int* n, 
00112                 const int ilo, const int ihi, double* H, const int ldH, 
00113                 double* wr, double* wi, double* Z, const int ldz, double* work,
00114                 const int* lwork){
00115             int info;
00116 //          std::cout << "I'm inside lapack::detail::hseqr_backend for doubles" 
00117 //              << std::endl;
00118             LAPACK_DHSEQR(job, compz, n, &ilo, &ihi, H, &ldH, wr, wi, 
00119                     Z, &ldz, work, lwork, &info);
00120             return info;
00121         }
00122 
00123         // complex<float>
00124         inline
00125         int hseqr_backend(const char* job, const char* compz, int* n, 
00126                 const int ilo, const int ihi, traits::complex_f* H, const int ldH, 
00127                 traits::complex_f* w, traits::complex_f* Z, int ldz, 
00128                 traits::complex_f* work, const int* lwork){
00129             int info;
00130 //          std::cout << "I'm inside lapack::detail::hseqr_backend for complex<float>" 
00131 //              << std::endl;
00132             LAPACK_CHSEQR(job, compz, n, &ilo, &ihi, 
00133                     traits::complex_ptr(H), &ldH, 
00134                     traits::complex_ptr(w), 
00135                     traits::complex_ptr(Z), &ldz, 
00136                     traits::complex_ptr(work), lwork, &info);
00137             return info;
00138         }
00139 
00140         // complex<double>
00141         inline
00142         int hseqr_backend(const char* job, const char* compz, int* n, 
00143                 const int ilo, const int ihi, traits::complex_d* H, const int ldH, 
00144                 traits::complex_d* w, traits::complex_d* Z, int ldz, 
00145                 traits::complex_d* work, const int* lwork){
00146             int info;
00147 //          std::cout << "I'm inside lapack::detail::hseqr_backend for complex<double>" 
00148 //              << std::endl;
00149             LAPACK_ZHSEQR(job, compz, n, &ilo, &ihi, 
00150                     traits::complex_ptr(H), &ldH, 
00151                     traits::complex_ptr(w), 
00152                     traits::complex_ptr(Z), &ldz, 
00153                     traits::complex_ptr(work), lwork, &info);
00154             return info;
00155         }
00156 
00157         template <int N>
00158         struct Hseqr{};
00159 
00160         template <>
00161         struct Hseqr< 1 >{
00162             template < typename A, typename W, typename V>
00163             int operator() ( const char job, const char compz, A& H, W& w, V& Z ){
00164 //              std::cout << "Inside Hseqr<1>." << std::endl;
00165 
00166                 int n = traits::matrix_size1(H);
00167                 typedef typename A::value_type value_type;
00168                 traits::detail::array<value_type> wr(n);
00169                 traits::detail::array<value_type> wi(n);
00170 
00171                 // workspace query
00172                 int lwork = -1;
00173                 value_type work_temp;
00174                 int result = detail::hseqr_backend(&job, &compz, &n, 1, n,
00175                                             traits::matrix_storage(H), 
00176                                             traits::leading_dimension(H),
00177                                             wr.storage(), wi.storage(),
00178                                             traits::matrix_storage(Z),
00179                                             traits::leading_dimension(Z),
00180                                             &work_temp, &lwork);
00181 
00182                 if( result !=0 ) return result;
00183 
00184                 lwork = (int) work_temp;
00185                 traits::detail::array<value_type> work(lwork);
00186                 result = detail::hseqr_backend(&job, &compz, &n, 1, n,
00187                                             traits::matrix_storage(H), 
00188                                             traits::leading_dimension(H),
00189                                             wr.storage(), wi.storage(),
00190                                             traits::matrix_storage(Z),
00191                                             traits::leading_dimension(Z),
00192                                             work.storage(), &lwork);
00193 
00194                 for (int i = 0; i < n; i++)
00195                     w[i] = std::complex<value_type>(wr[i], wi[i]);
00196 
00197                 return result;
00198             }
00199         };
00200 
00201         template <>
00202         struct Hseqr< 2 >{
00203             template < typename A, typename W, typename V>
00204             int operator() ( const char job, const char compz, A& H, W& w, V& Z ){
00205 //              std::cout << "Inside Hseqr<2>." << std::endl;
00206 
00207                 int n = traits::matrix_size1(H);
00208                 typedef typename A::value_type value_type;
00209 
00210                 // workspace query
00211                 int lwork = -1;
00212                 value_type work_temp;
00213                 int result = detail::hseqr_backend(&job, &compz, &n, 1, n,
00214                         traits::matrix_storage(H),
00215                         traits::leading_dimension(H), 
00216                         traits::vector_storage(w),
00217                         traits::matrix_storage(Z), traits::leading_dimension(Z),
00218                         &work_temp, &lwork);
00219 
00220                 if( result !=0 ) return result;
00221 
00222                 lwork = (int) std::real(work_temp);
00223                 traits::detail::array<value_type> work(lwork);
00224                 result = detail::hseqr_backend(&job, &compz, &n, 1, n,
00225                         traits::matrix_storage(H),
00226                         traits::leading_dimension(H), 
00227                         traits::vector_storage(w),
00228                         traits::matrix_storage(Z), traits::leading_dimension(Z),
00229                         work.storage(), &lwork);
00230 
00231                 return result;
00232             }
00233         };
00234         
00235         template < typename A, typename W, typename V>
00236         int hseqr( const char job, const char compz, A& H, W& w, V& Z ){
00237 //          std::cout << "I'm inside lapack::detail::hseqr." << std::endl;
00238 
00239             assert ( job == 'E' || job == 'S' );
00240             assert ( compz == 'N' || compz == 'I' || compz == 'V' );
00241 
00242             typedef typename A::value_type value_type;
00243 
00244             int result = detail::Hseqr< n_workspace_args<value_type>::value >()(
00245                     job, compz, H, w, Z);
00246 
00247             return result;
00248         }
00249     }   // namespace detail 
00250 
00251     // Compute eigenvalues without the Schur vectors
00252     template < typename A, typename W>
00253     int hseqr( const char job, A& H, W& w){
00254       // input checking
00255 #ifndef BOOST_NUMERIC_BINDINGS_NO_STRUCTURE_CHECK 
00256       BOOST_STATIC_ASSERT((boost::is_same<
00257                            typename traits::matrix_traits<A>::matrix_structure, 
00258                            traits::general_t
00259                            >::value)); 
00260 #endif 
00261 
00262 #ifndef NDEBUG
00263         int const n = traits::matrix_size1(H);
00264 #endif
00265 
00266         typedef typename A::value_type value_type;
00267         typedef typename W::value_type complex_value_type;
00268 
00269         assert(traits::matrix_size2(H) == n); // Square matrix
00270         assert(traits::vector_size(w) == n);  
00271 
00272         ublas::matrix<value_type, ublas::column_major> Z(1,1);
00273         return detail::hseqr( job, 'N', H, w, Z );
00274     }
00275 
00276     // Compute eigenvalues and the Schur vectors
00277     template < typename A, typename W, typename Z>
00278     int hseqr( const char job, const char compz, A& H, W& w, Z& z){
00279       // input checking
00280 #ifndef BOOST_NUMERIC_BINDINGS_NO_STRUCTURE_CHECK 
00281       BOOST_STATIC_ASSERT((boost::is_same<
00282                            typename traits::matrix_traits<A>::matrix_structure, 
00283                            traits::general_t
00284                            >::value)); 
00285 #endif 
00286 
00287 #ifndef NDEBUG
00288         int const n = traits::matrix_size1(H);
00289 #endif
00290 
00291         typedef typename A::value_type value_type;
00292         assert(traits::matrix_size2(H) == n); // Square matrix
00293         assert(traits::vector_size(w) == n);  
00294         assert(traits::matrix_size2(z) == n);
00295 
00296         return detail::hseqr( job, compz, H, w, z );
00297     }
00298 
00299   }
00300 }}}
00301 
00302 #endif

Generated on Wed Nov 23 19:00:17 2011 for FreeCAD by  doxygen 1.6.1