00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifndef BOOST_NUMERIC_BINDINGS_LAPACK_GEEV_HPP
00016 #define BOOST_NUMERIC_BINDINGS_LAPACK_GEEV_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
00025 #ifndef BOOST_NUMERIC_BINDINGS_NO_STRUCTURE_CHECK
00026 # include <boost/static_assert.hpp>
00027 # include <boost/type_traits.hpp>
00028 #endif
00029
00030
00031 namespace boost { namespace numeric { namespace bindings {
00032
00033 namespace lapack {
00034
00036
00037
00038
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 namespace detail {
00073
00074 inline
00075 int geev_backend(const char* jobvl, const char* jobvr, const int* n, float* a,
00076 const int* lda, float* wr, float* wi, float* vl, const int* ldvl,
00077 float* vr, const int* ldvr, float* work, const int* lwork)
00078 {
00079 int info;
00080 LAPACK_SGEEV(jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr, ldvr, work, lwork, &info);
00081 return info;
00082 }
00083
00084 inline
00085 int geev_backend(const char* jobvl, const char* jobvr, const int* n, double* a,
00086 const int* lda, double* wr, double* wi, double* vl, const int* ldvl,
00087 double* vr, const int* ldvr, double* work, const int* lwork)
00088 {
00089 int info;
00090 LAPACK_DGEEV(jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr, ldvr, work, lwork, &info);
00091 return info;
00092 }
00093
00094 inline
00095 int geev_backend(const char* jobvl, const char* jobvr, const int* n, traits::complex_f* a,
00096 const int* lda, traits::complex_f* w, traits::complex_f* vl, const int* ldvl,
00097 traits::complex_f* vr, const int* ldvr, traits::complex_f* work, const int* lwork,
00098 float* rwork)
00099 {
00100 int info;
00101 LAPACK_CGEEV(jobvl, jobvr, n,
00102 traits::complex_ptr(a), lda,
00103 traits::complex_ptr(w),
00104 traits::complex_ptr(vl), ldvl,
00105 traits::complex_ptr(vr), ldvr,
00106 traits::complex_ptr(work), lwork,
00107 rwork, &info);
00108 return info;
00109 }
00110
00111 inline
00112 int geev_backend(const char* jobvl, const char* jobvr, const int* n, traits::complex_d* a,
00113 const int* lda, traits::complex_d* w, traits::complex_d* vl, const int* ldvl,
00114 traits::complex_d* vr, const int* ldvr, traits::complex_d* work, const int* lwork,
00115 double* rwork)
00116 {
00117 int info;
00118 LAPACK_ZGEEV(jobvl, jobvr, n,
00119 traits::complex_ptr(a), lda,
00120 traits::complex_ptr(w),
00121 traits::complex_ptr(vl), ldvl,
00122 traits::complex_ptr(vr), ldvr,
00123 traits::complex_ptr(work), lwork,
00124 rwork, &info);
00125 return info;
00126 }
00127
00128
00129 struct real_case {};
00130 struct mixed_case {};
00131 struct complex_case {};
00132
00133
00134
00135
00136
00137 template <typename A, typename W, typename V>
00138 int geev(real_case, const char jobvl, const char jobvr, A& a, W& w,
00139 V* vl, V *vr)
00140 {
00141 int const n = traits::matrix_size1(a);
00142 typedef typename A::value_type value_type;
00143 traits::detail::array<value_type> wr(n);
00144 traits::detail::array<value_type> wi(n);
00145
00146 traits::detail::array<value_type> vl2(vl ? 0 : n);
00147 traits::detail::array<value_type> vr2(vr ? 0 : n);
00148 value_type* vl_real = vl ? traits::matrix_storage(*vl) : vl2.storage();
00149 const int ldvl = vl ? traits::matrix_size2(*vl) : 1;
00150 value_type* vr_real = vr ? traits::matrix_storage(*vr) : vr2.storage();
00151 const int ldvr = vr ? traits::matrix_size2(*vr) : 1;
00152
00153
00154
00155 int lwork = -1;
00156 value_type work_temp;
00157 int result = geev_backend(&jobvl, &jobvr, &n,
00158 traits::matrix_storage(a), &n,
00159 wr.storage(), wi.storage(),
00160 vl_real, &ldvl, vr_real, &ldvr,
00161 &work_temp, &lwork);
00162 if (result != 0)
00163 return result;
00164
00165 lwork = (int) work_temp;
00166 traits::detail::array<value_type> work(lwork);
00167 result = geev_backend(&jobvl, &jobvr, &n,
00168 traits::matrix_storage(a), &n,
00169 wr.storage(), wi.storage(),
00170 vl_real, &ldvl, vr_real, &ldvr,
00171 work.storage(), &lwork);
00172
00173 for (int i = 0; i < n; i++)
00174 w[i] = std::complex<value_type>(wr[i], wi[i]);
00175 return result;
00176 }
00177
00178
00179 template <typename A, typename W, typename V>
00180 int geev(mixed_case, const char jobvl, const char jobvr, A& a, W& w,
00181 V* vl, V *vr)
00182 {
00183 int const n = traits::matrix_size1(a);
00184 typedef typename A::value_type value_type;
00185 traits::detail::array<value_type> wr(n);
00186 traits::detail::array<value_type> wi(n);
00187
00188 traits::detail::array<value_type> vl2(vl ? n*n : n);
00189 traits::detail::array<value_type> vr2(vr ? n*n : n);
00190 const int ldvl2 = vl ? n : 1;
00191 const int ldvr2 = vr ? n : 1;
00192
00193
00194 int lwork = -1;
00195 value_type work_temp;
00196 int result = geev_backend(&jobvl, &jobvr, &n,
00197 traits::matrix_storage(a), &n,
00198 wr.storage(), wi.storage(),
00199 vl2.storage(), &ldvl2, vr2.storage(), &ldvr2,
00200 &work_temp, &lwork);
00201 if (result != 0)
00202 return result;
00203
00204 lwork = (int) work_temp;
00205 traits::detail::array<value_type> work(lwork);
00206 result = geev_backend(&jobvl, &jobvr, &n,
00207 traits::matrix_storage(a), &n,
00208 wr.storage(), wi.storage(),
00209 vl2.storage(), &ldvl2, vr2.storage(), &ldvr2,
00210 work.storage(), &lwork);
00211
00212 typedef typename V::value_type vec_value_type;
00213 vec_value_type* vl_stor = NULL;
00214 vec_value_type* vr_stor = NULL;
00215 int ldvl = 0, ldvr = 0;
00216 if (vl)
00217 {
00218 vl_stor = traits::matrix_storage(*vl);
00219 ldvl = traits::matrix_size2(*vl);
00220 }
00221 if (vr)
00222 {
00223 vr_stor = traits::matrix_storage(*vr);
00224 ldvr = traits::matrix_size2(*vr);
00225 }
00226
00227 for (int i = 0; i < n; i++)
00228 {
00229 w[i] = std::complex<value_type>(wr[i], wi[i]);
00230 if (wi[i] != 0)
00231 {
00232 assert(i+1 < n);
00233 assert(wr[i+1] == wr[i]);
00234 assert(wi[i+1] == -wi[i]);
00235
00236 w[i+1] = std::complex<value_type>(wr[i+1], wi[i+1]);
00237 for (int j = 0; j < n; j++)
00238 {
00239 if (vl)
00240 {
00241 vl_stor[i*ldvl+j] = std::complex<value_type>(vl2[i*n+j], vl2[(i+1)*n+j]);
00242 vl_stor[(i+1)*ldvl+j] = std::complex<value_type>(vl2[i*n+j], -vl2[(i+1)*n+j]);
00243 }
00244 if (vr)
00245 {
00246 vr_stor[i*ldvr+j] = std::complex<value_type>(vr2[i*n+j], vr2[(i+1)*n+j]);
00247 vr_stor[(i+1)*ldvr+j] = std::complex<value_type>(vr2[i*n+j], -vr2[(i+1)*n+j]);
00248 }
00249 }
00250
00251 i++;
00252 }
00253 else
00254 {
00255 for (int j = 0; j < n; j++)
00256 {
00257 if (vl)
00258 vl_stor[i*ldvl+j] = vl2[i*n+j];
00259 if (vr)
00260 vr_stor[i*ldvr+j] = vr2[i*n+j];
00261 }
00262 }
00263 }
00264 return result;
00265 }
00266
00267
00268 template <typename A, typename W, typename V>
00269 int geev(complex_case, const char jobvl, const char jobvr, A& a, W& w,
00270 V* vl, V *vr)
00271 {
00272 typedef typename A::value_type value_type;
00273 typedef typename traits::type_traits<value_type>::real_type real_type;
00274
00275 int const n = traits::matrix_size1(a);
00276 traits::detail::array<real_type> rwork(2*n);
00277
00278 traits::detail::array<value_type> vl2(vl ? 0 : n);
00279 traits::detail::array<value_type> vr2(vr ? 0 : n);
00280 value_type* vl_real = vl ? traits::matrix_storage(*vl) : vl2.storage();
00281 const int ldvl = vl ? traits::matrix_size2(*vl) : 1;
00282 value_type* vr_real = vr ? traits::matrix_storage(*vr) : vr2.storage();
00283 const int ldvr = vr ? traits::matrix_size2(*vr) : 1;
00284
00285
00286 int lwork = -1;
00287 value_type work_temp;
00288 int result = geev_backend(&jobvl, &jobvr, &n,
00289 traits::matrix_storage(a), &n,
00290 traits::vector_storage(w),
00291 vl_real, &ldvl, vr_real, &ldvr,
00292 &work_temp, &lwork, rwork.storage());
00293 if (result != 0)
00294 return result;
00295
00296 lwork = (int) std::real(work_temp);
00297 traits::detail::array<value_type> work(lwork);
00298 result = geev_backend(&jobvl, &jobvr, &n,
00299 traits::matrix_storage(a), &n,
00300 traits::vector_storage(w),
00301 vl_real, &ldvl, vr_real, &ldvr,
00302 work.storage(), &lwork,
00303 rwork.storage());
00304
00305 return result;
00306 }
00307
00308 }
00309
00310
00311
00312 template <typename A, typename W, typename V>
00313 int geev(A& a, W& w, V* vl, V* vr, optimal_workspace)
00314 {
00315
00316 #ifndef BOOST_NUMERIC_BINDINGS_NO_STRUCTURE_CHECK
00317 BOOST_STATIC_ASSERT((boost::is_same<
00318 typename traits::matrix_traits<A>::matrix_structure,
00319 traits::general_t
00320 >::value));
00321 #endif
00322
00323 #ifndef NDEBUG
00324 int const n = traits::matrix_size1(a);
00325 #endif
00326
00327 assert(traits::matrix_size2(a)==n);
00328 assert(traits::vector_size(w)==n);
00329 assert(traits::vector_size(w)==n);
00330 assert(!vr || traits::matrix_size1(*vr)==n);
00331 assert(!vl || traits::matrix_size1(*vl)==n);
00332
00333
00334 typedef typename A::value_type value_type;
00335 typedef typename V::value_type vec_value_type;
00336 typedef typename traits::type_traits<value_type>::real_type real_type;
00337
00338
00339 return detail::geev(typename boost::mpl::if_<
00340 boost::is_same<value_type, real_type>,
00341 typename boost::mpl::if_<
00342 boost::is_same<vec_value_type, real_type>,
00343 detail::real_case,
00344 detail::mixed_case>::type,
00345 detail::complex_case>::type(),
00346 vl != 0 ? 'V' : 'N',
00347 vr != 0 ? 'V' : 'N',
00348 a, w, vl, vr);
00349 }
00350
00351 }
00352
00353 }}}
00354
00355 #endif