heevd.hpp

Go to the documentation of this file.
00001 /*
00002  * 
00003  * Copyright Toon Knapen, Karl Meerbergen & Kresimir Fresl 2003
00004  * Copyright Thomas Klimpel 2008
00005  *
00006  * Distributed under the Boost Software License, Version 1.0.
00007  * (See accompanying file LICENSE_1_0.txt or copy at
00008  * http://www.boost.org/LICENSE_1_0.txt)
00009  *
00010  * KF acknowledges the support of the Faculty of Civil Engineering,
00011  * University of Zagreb, Croatia.
00012  *
00013  */
00014 
00015 #ifndef BOOST_NUMERIC_BINDINGS_LAPACK_HEEVD_HPP
00016 #define BOOST_NUMERIC_BINDINGS_LAPACK_HEEVD_HPP
00017 
00018 #include <boost/numeric/bindings/traits/traits.hpp>
00019 #include <boost/numeric/bindings/traits/type.hpp>
00020 #include <boost/numeric/bindings/lapack/lapack.h>
00021 #include <boost/numeric/bindings/lapack/workspace.hpp>
00022 #include <boost/numeric/bindings/traits/detail/array.hpp>
00023 
00024 #ifndef BOOST_NUMERIC_BINDINGS_NO_STRUCTURE_CHECK
00025 #  include <boost/static_assert.hpp>
00026 #  include <boost/type_traits.hpp>
00027 #endif
00028 
00029 
00030 namespace boost { namespace numeric { namespace bindings {
00031 
00032   namespace lapack {
00033 
00035     //
00036     // Eigendecomposition of a complex Hermitian matrix A = Q * D * Q'
00037     //
00039 
00040     /*
00041      * heevd() computes all eigenvalues and, optionally, eigenvectors of a
00042      * complex Hermitian matrix A.  If eigenvectors are desired, it uses a
00043      * divide and conquer algorithm.
00044      *
00045      * heevd() computes the eigendecomposition of a N x N matrix
00046      * A = Q * D * Q',  where Q is a N x N unitary matrix and
00047      * D is a diagonal matrix. The diagonal element D(i,i) is an
00048      * eigenvalue of A and Q(:,i) is a corresponding eigenvector.
00049      * The eigenvalues are stored in ascending order.
00050      *
00051      * On return of heevd, A is overwritten with the eigenvectors from Q
00052      * and w contains the eigenvalues from the main diagonal of D.
00053      *
00054      * int heevd (char jobz, char uplo, A& a, W& w, Work work) {
00055      *    jobz :  'V' : compute eigenvectors
00056      *            'N' : do not compute eigenvectors
00057      *    uplo :  'U' : only the upper triangular part of A is used on input.
00058      *            'L' : only the lower triangular part of A is used on input.
00059      */
00060 
00061     namespace detail {
00062 
00063       inline void heevd (
00064         char const jobz, char const uplo, int const n,
00065         float* a, int const lda,
00066         float* w, float* work, int const lwork,
00067         int* iwork, int const liwork, int& info)
00068       {
00069         LAPACK_SSYEVD (
00070           &jobz, &uplo, &n,
00071           a, &lda,
00072           w, work, &lwork,
00073           iwork, &liwork, &info);
00074       }
00075 
00076       inline void heevd (
00077         char const jobz, char const uplo, int const n,
00078         double* a, int const lda,
00079         double* w, double* work, int const lwork,
00080         int* iwork, int const liwork, int& info)
00081       {
00082         LAPACK_DSYEVD (
00083           &jobz, &uplo, &n,
00084           a, &lda,
00085           w, work, &lwork,
00086           iwork, &liwork, &info);
00087       }
00088 
00089       inline void heevd (
00090         char const jobz, char const uplo, int const n,
00091         traits::complex_f* a, int const lda,
00092         float* w, traits::complex_f* work, int const lwork,
00093         float* rwork, int const lrwork, int* iwork, int const liwork, int& info)
00094       {
00095         LAPACK_CHEEVD (
00096           &jobz, &uplo, &n,
00097           traits::complex_ptr(a), &lda,
00098           w,
00099           traits::complex_ptr(work), &lwork,
00100           rwork, &lrwork, iwork, &liwork, &info);
00101       }
00102 
00103       inline void heevd (
00104         char const jobz, char const uplo, int const n,
00105         traits::complex_d* a, int const lda,
00106         double* w, traits::complex_d* work, int const lwork,
00107         double* rwork, int const lrwork, int* iwork, int const liwork, int& info)
00108       {
00109         LAPACK_ZHEEVD (
00110           &jobz, &uplo, &n,
00111           traits::complex_ptr(a), &lda,
00112           w,
00113           traits::complex_ptr(work), &lwork,
00114           rwork, &lrwork, iwork, &liwork, &info);
00115       }
00116     } // namespace detail
00117 
00118     namespace detail {
00119 
00120       template <int N>
00121       struct Heevd{};
00122 
00124       template <>
00125       struct Heevd< 1 > {
00126         // Function that allocates temporary arrays
00127         template <typename T, typename R>
00128         void operator() (
00129           char const jobz, char const uplo, int const n,
00130           T* a, int const lda,
00131           R* w, minimal_workspace, int& info) {
00132 
00133           traits::detail::array<T> work( jobz=='N' ? 1+2*n : 1+6*n+2*n*n );
00134           traits::detail::array<int> iwork( jobz=='N' ? 1 : 3+5*n );
00135 
00136           heevd( jobz, uplo, n, a, lda, w,
00137             traits::vector_storage (work), traits::vector_size (work),
00138             traits::vector_storage (iwork), traits::vector_size (iwork),
00139             info);
00140         }
00141         // Function that allocates temporary arrays
00142         template <typename T, typename R>
00143         void operator() (
00144           char const jobz, char const uplo, int const n,
00145           T* a, int const lda,
00146           R* w, optimal_workspace, int& info) {
00147 
00148           traits::detail::array<int> iwork( jobz=='N' ? 1 : 3+5*n );
00149 
00150           T workspace_query;
00151           heevd( jobz, uplo, n, a, lda, w,
00152             &workspace_query, -1,
00153             traits::vector_storage (iwork), traits::vector_size (iwork),
00154             info);
00155 
00156           traits::detail::array<T> work( static_cast<int>( workspace_query ) );
00157 
00158           heevd( jobz, uplo, n, a, lda, w,
00159             traits::vector_storage (work), traits::vector_size (work),
00160             traits::vector_storage (iwork), traits::vector_size (iwork),
00161             info);
00162         }
00163         // Function that uses given workarrays
00164         template <typename T, typename R, typename W, typename WI>
00165         void operator() (
00166           char const jobz, char const uplo, int const n,
00167           T* a, int const lda,
00168           R* w, std::pair<detail::workspace1<W>, detail::workspace1<WI> > work, int& info) {
00169 
00170           assert (traits::vector_size (work.first.w_) >= jobz=='N' ? 1+2*n : 1+6*n+2*n*n);
00171           assert (traits::vector_size (work.second.w_) >= jobz=='N' ? 1 : 3+5*n);
00172 
00173           heevd( jobz, uplo, n, a, lda, w,
00174             traits::vector_storage (work.first.w_), traits::vector_size (work.first.w_),
00175             traits::vector_storage (work.second.w_), traits::vector_size (work.second.w_),
00176             info);
00177         }
00178       };
00179 
00181       template <>
00182       struct Heevd< 2 > {
00183         // Function that allocates temporary arrays
00184         template <typename T, typename R>
00185         void operator() (
00186           char const jobz, char const uplo, int const n,
00187           T* a, int const lda,
00188           R* w, minimal_workspace, int& info) {
00189 
00190           traits::detail::array<T> work( jobz=='N' ? 1+n : 2*n+n*n );
00191           traits::detail::array<R> rwork( jobz=='N' ? n : 1+5*n+2*n*n );
00192           traits::detail::array<int> iwork( jobz=='N' ? 1 : 3+5*n );
00193 
00194           heevd( jobz, uplo, n, a, lda, w,
00195             traits::vector_storage (work), traits::vector_size (work),
00196             traits::vector_storage (rwork), traits::vector_size (rwork),
00197             traits::vector_storage (iwork), traits::vector_size (iwork),
00198             info);
00199         }
00200         // Function that allocates temporary arrays
00201         template <typename T, typename R>
00202         void operator() (
00203           char const jobz, char const uplo, int const n,
00204           T* a, int const lda,
00205           R* w, optimal_workspace, int& info) {
00206 
00207           traits::detail::array<R> rwork( jobz=='N' ? n : 1+5*n+2*n*n );
00208           traits::detail::array<int> iwork( jobz=='N' ? 1 : 3+5*n );
00209 
00210           T workspace_query;
00211           heevd( jobz, uplo, n, a, lda, w,
00212             &workspace_query, -1,
00213             traits::vector_storage (rwork), traits::vector_size (rwork),
00214             traits::vector_storage (iwork), traits::vector_size (iwork),
00215             info);
00216 
00217           traits::detail::array<T> work( static_cast<int>( traits::real( workspace_query ) ) );
00218 
00219           heevd( jobz, uplo, n, a, lda, w,
00220             traits::vector_storage (work), traits::vector_size (work),
00221             traits::vector_storage (rwork), traits::vector_size (rwork),
00222             traits::vector_storage (iwork), traits::vector_size (iwork),
00223             info);
00224         }
00225         // Function that uses given workarrays
00226         template <typename T, typename R, typename WC, typename WR, typename WI>
00227         void operator() (
00228           char const jobz, char const uplo, int const n,
00229           T* a, int const lda,
00230           R* w, std::pair<detail::workspace2<WC,WR>, detail::workspace1<WI> > work, int& info) {
00231 
00232           assert (traits::vector_size (work.first.w_) >= jobz=='N' ? 1+n : 2*n+n*n);
00233           assert (traits::vector_size (work.first.wr_) >= jobz=='N' ? n : 1+5*n+2*n*n);
00234           assert (traits::vector_size (work.second.w_) >= jobz=='N' ? 1 : 3+5*n);
00235 
00236           heevd( jobz, uplo, n, a, lda, w,
00237             traits::vector_storage (work.first.w_), traits::vector_size (work.first.w_),
00238             traits::vector_storage (work.first.wr_), traits::vector_size (work.first.wr_),
00239             traits::vector_storage (work.second.w_), traits::vector_size (work.second.w_),
00240             info);
00241         }
00242       };
00243     } // namespace detail
00244 
00245     template <typename A, typename W, typename Work>
00246     inline int heevd (
00247       char jobz, char uplo, A& a,
00248       W& w, Work work = optimal_workspace() ) {
00249 
00250 #ifndef BOOST_NUMERIC_BINDINGS_NO_STRUCTURE_CHECK
00251       BOOST_STATIC_ASSERT((boost::is_same<
00252         typename traits::matrix_traits<A>::matrix_structure, 
00253         traits::general_t
00254       >::value));
00255 #endif
00256 
00257       int const n = traits::matrix_size1 (a);
00258       assert (traits::matrix_size2 (a) == n);
00259       assert (traits::vector_size (w) == n);
00260       assert ( uplo=='U' || uplo=='L' );
00261       assert ( jobz=='N' || jobz=='V' );
00262 
00263       int info; 
00264       detail::Heevd< n_workspace_args<typename A::value_type>::value >() (
00265         jobz, uplo, n,
00266         traits::matrix_storage (a),
00267         traits::leading_dimension (a),
00268         traits::vector_storage (w),
00269         work,
00270         info);
00271       return info;
00272     }
00273   }
00274 
00275 }}}
00276 
00277 #endif

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