heevx.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_HEEVX_HPP
00016 #define BOOST_NUMERIC_BINDINGS_LAPACK_HEEVX_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      * heevx() computes selected eigenvalues and, optionally, eigenvectors
00042      * of a complex Hermitian matrix A.  Eigenvalues and eigenvectors can
00043      * be selected by specifying either a range of values or a range of
00044      * indices for the desired eigenvalues.
00045      *
00046      * heevx() computes the eigendecomposition of a N x N matrix
00047      * A = Q * D * Q',  where Q is a N x N unitary matrix and
00048      * D is a diagonal matrix. The diagonal element D(i,i) is an
00049      * eigenvalue of A and Q(:,i) is a corresponding eigenvector.
00050      * The eigenvalues are stored in ascending order.
00051      *
00052      * On return of heevx, A is overwritten, z contains selected eigenvectors from Q
00053      * and w contains selected eigenvalues from the main diagonal of D.
00054      *
00055      * int heevx (char jobz, char range, char uplo, A& a, T vl, T vu, int il, int iu, T abstol, int& m,
00056      *            W& w, Z& z, IFail& ifail, Work work) {
00057      *    jobz :  'V' : compute eigenvectors
00058      *            'N' : do not compute eigenvectors
00059      *    range : 'A': all eigenvalues will be found.
00060      *            'V': all eigenvalues in the half-open interval (vl,vu] will be found.
00061      *            'I': the il-th through iu-th eigenvalues will be found.
00062      *    uplo :  'U' : only the upper triangular part of A is used on input.
00063      *            'L' : only the lower triangular part of A is used on input.
00064      */
00065 
00066     namespace detail {
00067 
00068       inline void heevx (
00069         char const jobz, char const range, char const uplo, int const n,
00070         float* a, int const lda,
00071         float const vl, float const vu, int const il, int const iu,
00072         float const abstol, int& m,
00073         float* w, float* z, int const ldz, float* work, int const lwork,
00074         int* iwork, int* ifail, int& info)
00075       {
00076         LAPACK_SSYEVX (
00077           &jobz, &range, &uplo, &n,
00078           a, &lda,
00079           &vl, &vu, &il, &iu,
00080           &abstol, &m,
00081           w, z, &ldz, work, &lwork,
00082           iwork, ifail, &info);
00083       }
00084 
00085       inline void heevx (
00086         char const jobz, char const range, char const uplo, int const n,
00087         double* a, int const lda,
00088         double const vl, double const vu, int const il, int const iu,
00089         double const abstol, int& m,
00090         double* w, double* z, int const ldz, double* work, int const lwork,
00091         int* iwork, int* ifail, int& info)
00092       {
00093         LAPACK_DSYEVX (
00094           &jobz, &range, &uplo, &n,
00095           a, &lda,
00096           &vl, &vu, &il, &iu,
00097           &abstol, &m,
00098           w, z, &ldz, work, &lwork,
00099           iwork, ifail, &info);
00100       }
00101 
00102       inline void heevx (
00103         char const jobz, char const range, char const uplo, int const n,
00104         traits::complex_f* a, int const lda,
00105         float const vl, float const vu, int const il, int const iu,
00106         float const abstol, int& m,
00107         float* w, traits::complex_f* z, int const ldz, traits::complex_f* work, int const lwork,
00108         float* rwork, int* iwork, int* ifail, int& info)
00109       {
00110         LAPACK_CHEEVX (
00111           &jobz, &range, &uplo, &n,
00112           traits::complex_ptr(a), &lda,
00113           &vl, &vu, &il, &iu, &abstol, &m, w,
00114           traits::complex_ptr(z), &ldz,
00115           traits::complex_ptr(work), &lwork,
00116           rwork, iwork, ifail, &info);
00117       }
00118 
00119       inline void heevx (
00120         char const jobz, char const range, char const uplo, int const n,
00121         traits::complex_d* a, int const lda,
00122         double const vl, double const vu, int const il, int const iu,
00123         double const abstol, int& m,
00124         double* w, traits::complex_d* z, int const ldz, traits::complex_d* work, int const lwork,
00125         double* rwork, int* iwork, int* ifail, int& info)
00126       {
00127         LAPACK_ZHEEVX (
00128           &jobz, &range, &uplo, &n,
00129           traits::complex_ptr(a), &lda,
00130           &vl, &vu, &il, &iu, &abstol, &m, w,
00131           traits::complex_ptr(z), &ldz,
00132           traits::complex_ptr(work), &lwork,
00133           rwork, iwork, ifail, &info);
00134       }
00135     } // namespace detail
00136 
00137     namespace detail {
00138 
00139       template <int N>
00140       struct Heevx{};
00141 
00143       template <>
00144       struct Heevx< 1 > {
00145         // Function that allocates temporary arrays
00146         template <typename T, typename R>
00147         void operator() (
00148           char const jobz, char const range, char const uplo, int const n,
00149           T* a, int const lda,
00150           R vl, R vu, int const il, int const iu,
00151           R abstol, int& m,
00152           R* w, T* z, int const ldz, minimal_workspace, int* ifail, int& info) {
00153 
00154           traits::detail::array<T> work( 8*n );
00155           traits::detail::array<int> iwork( 5*n );
00156 
00157           heevx( jobz, range, uplo, n, a, lda, vl, vu, il, iu, abstol, m, w, z, ldz,
00158             traits::vector_storage (work), traits::vector_size (work),
00159             traits::vector_storage (iwork),
00160             ifail, info);
00161         }
00162         // Function that allocates temporary arrays
00163         template <typename T, typename R>
00164         void operator() (
00165           char const jobz, char const range, char const uplo, int const n,
00166           T* a, int const lda,
00167           R vl, R vu, int const il, int const iu,
00168           R abstol, int& m,
00169           R* w, T* z, int const ldz, optimal_workspace, int* ifail, int& info) {
00170 
00171           traits::detail::array<int> iwork( 5*n );
00172 
00173           T workspace_query;
00174           heevx( jobz, range, uplo, n, a, lda, vl, vu, il, iu, abstol, m, w, z, ldz,
00175             &workspace_query, -1,
00176             traits::vector_storage (iwork),
00177             ifail, info);
00178 
00179           traits::detail::array<T> work( static_cast<int>( workspace_query ) );
00180 
00181           heevx( jobz, range, uplo, n, a, lda, vl, vu, il, iu, abstol, m, w, z, ldz,
00182             traits::vector_storage (work), traits::vector_size (work),
00183             traits::vector_storage (iwork),
00184             ifail, info);
00185         }
00186         // Function that uses given workarrays
00187         template <typename T, typename R, typename W, typename WI>
00188         void operator() (
00189           char const jobz, char const range, char const uplo, int const n,
00190           T* a, int const lda,
00191           R vl, R vu, int const il, int const iu,
00192           R abstol, int& m,
00193           R* w, T* z, int const ldz, std::pair<detail::workspace1<W>, detail::workspace1<WI> > work, int* ifail, int& info) {
00194 
00195           assert (traits::vector_size (work.first.w_) >= 8*n);
00196           assert (traits::vector_size (work.second.w_) >= 5*n);
00197 
00198           heevx( jobz, range, uplo, n, a, lda, vl, vu, il, iu, abstol, m, w, z, ldz,
00199             traits::vector_storage (work.first.w_), traits::vector_size (work.first.w_),
00200             traits::vector_storage (work.second.w_),
00201             ifail, info);
00202         }
00203       };
00204 
00206       template <>
00207       struct Heevx< 2 > {
00208         // Function that allocates temporary arrays
00209         template <typename T, typename R>
00210         void operator() (
00211           char const jobz, char const range, char const uplo, int const n,
00212           T* a, int const lda,
00213           R vl, R vu, int const il, int const iu,
00214           R abstol, int& m,
00215           R* w, T* z, int const ldz, minimal_workspace, int* ifail, int& info) {
00216 
00217           traits::detail::array<T> work( 2*n );
00218           traits::detail::array<R> rwork( 7*n );
00219           traits::detail::array<int> iwork( 5*n );
00220 
00221           heevx( jobz, range, uplo, n, a, lda, vl, vu, il, iu, abstol, m, w, z, ldz,
00222             traits::vector_storage (work), traits::vector_size (work),
00223             traits::vector_storage (rwork),
00224             traits::vector_storage (iwork),
00225             ifail, info);
00226         }
00227         // Function that allocates temporary arrays
00228         template <typename T, typename R>
00229         void operator() (
00230           char const jobz, char const range, char const uplo, int const n,
00231           T* a, int const lda,
00232           R vl, R vu, int const il, int const iu,
00233           R abstol, int& m,
00234           R* w, T* z, int const ldz, optimal_workspace, int* ifail, int& info) {
00235 
00236           traits::detail::array<R> rwork( 7*n );
00237           traits::detail::array<int> iwork( 5*n );
00238 
00239           T workspace_query;
00240           heevx( jobz, range, uplo, n, a, lda, vl, vu, il, iu, abstol, m, w, z, ldz,
00241             &workspace_query, -1,
00242             traits::vector_storage (rwork),
00243             traits::vector_storage (iwork),
00244             ifail, info);
00245 
00246           traits::detail::array<T> work( static_cast<int>( traits::real( workspace_query ) ) );
00247 
00248           heevx( jobz, range, uplo, n, a, lda, vl, vu, il, iu, abstol, m, w, z, ldz,
00249             traits::vector_storage (work), traits::vector_size (work),
00250             traits::vector_storage (rwork),
00251             traits::vector_storage (iwork),
00252             ifail, info);
00253         }
00254         // Function that uses given workarrays
00255         template <typename T, typename R, typename WC, typename WR, typename WI>
00256         void operator() (
00257           char const jobz, char const range, char const uplo, int const n,
00258           T* a, int const lda,
00259           R vl, R vu, int const il, int const iu,
00260           R abstol, int& m,
00261           R* w, T* z, int const ldz, std::pair<detail::workspace2<WC,WR>, detail::workspace1<WI> > work, int* ifail, int& info) {
00262 
00263           assert (traits::vector_size (work.first.w_) >= 2*n);
00264           assert (traits::vector_size (work.first.wr_) >= 7*n);
00265           assert (traits::vector_size (work.second.w_) >= 5*n);
00266 
00267           heevx( jobz, range, uplo, n, a, lda, vl, vu, il, iu, abstol, m, w, z, ldz,
00268             traits::vector_storage (work.first.w_), traits::vector_size (work.first.w_),
00269             traits::vector_storage (work.first.wr_),
00270             traits::vector_storage (work.second.w_),
00271             ifail, info);
00272         }
00273       };
00274     } // namespace detail
00275 
00276     template <typename A, typename T, typename W, typename Z, typename IFail, typename Work>
00277     inline int heevx (
00278       char jobz, char range, A& a, T vl, T vu, int il, int iu, T abstol, int& m,
00279       W& w, Z& z, IFail& ifail, Work work = optimal_workspace() ) {
00280 
00281 #ifndef BOOST_NUMERIC_BINDINGS_NO_STRUCTURE_CHECK
00282       typedef typename A::value_type                               value_type ;
00283       typedef typename traits::type_traits< value_type >::real_type real_type ;
00284       BOOST_STATIC_ASSERT((boost::is_same<
00285         typename traits::matrix_traits<A>::matrix_structure, 
00286         traits::hermitian_t
00287       >::value || (boost::is_same<
00288         typename traits::matrix_traits<A>::matrix_structure,
00289         traits::symmetric_t
00290       >::value && boost::is_same<value_type, real_type>::value)));
00291 #endif
00292 
00293       int const n = traits::matrix_size1 (a);
00294       assert (traits::matrix_size2 (a) == n);
00295       assert (traits::vector_size (w) == n);
00296       assert (traits::vector_size (ifail) == n);
00297       assert ( range=='A' || range=='V' || range=='I' );
00298       char uplo = traits::matrix_uplo_tag (a);
00299       assert ( uplo=='U' || uplo=='L' );
00300       assert ( jobz=='N' || jobz=='V' );
00301 
00302       int info; 
00303       detail::Heevx< n_workspace_args<typename A::value_type>::value >() (
00304         jobz, range, uplo, n,
00305         traits::matrix_storage (a),
00306         traits::leading_dimension (a),
00307         vl, vu, il, iu, abstol, m,
00308         traits::vector_storage (w),
00309         traits::matrix_storage (z),
00310         traits::leading_dimension (z),
00311         work,
00312         traits::vector_storage (ifail),
00313         info);
00314       return info;
00315     }
00316   }
00317 
00318 }}}
00319 
00320 #endif

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