blitz::Array<T, rank> f_to_c(blitz::Array<T, rank> &arr) { // Initialize an 11-dim vector of transpositions // (because transpose() doesn't take a TinyVector) int const max_dims = 11; int rev[max_dims]; for (int i=rank; i<max_dims; ++i) rev[i] = 0; // Reverse dimensions for (int i=0; i<rank; ++i) rev[i] = rank-1-i; auto ret(arr.transpose(rev[0], rev[1], rev[2], rev[3], rev[4], rev[5], rev[6], rev[7], rev[8], rev[9], rev[10])); // Re-base to 0 blitz::TinyVector<int, rank> base(0); ret.reindexSelf(base); return ret; }
void bob::math::eigSym_(const blitz::Array<double,2>& A, const blitz::Array<double,2>& B, blitz::Array<double,2>& V, blitz::Array<double,1>& D) { // Size variable const int N = A.extent(0); // Prepares to call LAPACK function // Initialises LAPACK variables const int itype = 1; const char jobz = 'V'; // Get both the eigenvalues and the eigenvectors const char uplo = 'U'; int info = 0; const int lda = N; const int ldb = N; // Initialises LAPACK arrays blitz::Array<double,2> A_blitz_lapack; // Tries to use V directly blitz::Array<double,2> Vt = V.transpose(1,0); const bool V_direct_use = bob::core::array::isCZeroBaseContiguous(Vt); if (V_direct_use) { A_blitz_lapack.reference(Vt); // Ugly fix for non-const transpose A_blitz_lapack = const_cast<blitz::Array<double,2>&>(A).transpose(1,0); } else // Ugly fix for non-const transpose A_blitz_lapack.reference( bob::core::array::ccopy(const_cast<blitz::Array<double,2>&>(A).transpose(1,0))); double *A_lapack = A_blitz_lapack.data(); // Ugly fix for non-const transpose blitz::Array<double,2> B_blitz_lapack( bob::core::array::ccopy(const_cast<blitz::Array<double,2>&>(B).transpose(1,0))); double *B_lapack = B_blitz_lapack.data(); blitz::Array<double,1> D_blitz_lapack; const bool D_direct_use = bob::core::array::isCZeroBaseContiguous(D); if (D_direct_use) D_blitz_lapack.reference(D); else D_blitz_lapack.resize(D.shape()); double *D_lapack = D_blitz_lapack.data(); // Calls the LAPACK function // A/ Queries the optimal size of the working arrays const int lwork_query = -1; double work_query; const int liwork_query = -1; int iwork_query; dsygvd_( &itype, &jobz, &uplo, &N, A_lapack, &lda, B_lapack, &ldb, D_lapack, &work_query, &lwork_query, &iwork_query, &liwork_query, &info); // B/ Computes the generalized eigenvalue decomposition const int lwork = static_cast<int>(work_query); boost::shared_array<double> work(new double[lwork]); const int liwork = static_cast<int>(iwork_query); boost::shared_array<int> iwork(new int[liwork]); dsygvd_( &itype, &jobz, &uplo, &N, A_lapack, &lda, B_lapack, &ldb, D_lapack, work.get(), &lwork, iwork.get(), &liwork, &info); // Checks info variable if (info != 0) throw std::runtime_error("The LAPACK function 'dsygvd' returned a non-zero value. This might be caused by a non-positive definite B matrix."); // Copy singular vectors back to V if required if (!V_direct_use) V = A_blitz_lapack.transpose(1,0); // Copy result back to sigma if required if (!D_direct_use) D = D_blitz_lapack; }