78 Eigen::MatrixXd
S = Eigen::MatrixXd::Zero(ncols, ncols);
79 if (nblocks == 0 || ncols == 0) {
87 const Index nt = (ncols + bs - 1) / bs;
88 if (nt * (nt + 1) / 2 >= 4 * nthreads) {
93 const auto tiles = LowerTiles(ncols, bs);
100 const Index max_rows =
101 std::max<Index>(1,
static_cast<Index>(budget / (8.0 *
double(ncols))));
103 std::vector<Eigen::VectorXd> w(
static_cast<std::size_t
>(nblocks));
105 while (first < nblocks) {
110 weights(last, w[std::size_t(last)]);
111 nrows += w[std::size_t(last)].size();
113 }
while (last < nblocks && nrows < max_rows);
116 std::vector<Index> pos_offset(std::size_t(last - first) + 1, 0);
117 std::vector<Index> neg_offset(std::size_t(last - first) + 1, 0);
118 for (
Index m = first; m < last; ++m) {
119 const Eigen::VectorXd& wm = w[std::size_t(m)];
120 const Index npos = (wm.array() > 0.0).count();
121 const Index nneg = (wm.array() < 0.0).count();
122 const std::size_t k = std::size_t(m - first);
123 pos_offset[k + 1] = pos_offset[k] + npos;
124 neg_offset[k + 1] = neg_offset[k] + nneg;
126 Eigen::MatrixXd Xp(pos_offset.back(), ncols);
127 Eigen::MatrixXd Xn(neg_offset.back(), ncols);
129#pragma omp parallel for schedule(dynamic)
130 for (
Index m = first; m < last; ++m) {
131 const std::size_t k = std::size_t(m - first);
132 const Eigen::VectorXd& wm = w[std::size_t(m)];
133 const Index npos = pos_offset[k + 1] - pos_offset[k];
134 const Index nneg = neg_offset[k + 1] - neg_offset[k];
135 auto Xp_m = Xp.middleRows(pos_offset[k], npos);
136 auto Xn_m = Xn.middleRows(neg_offset[k], nneg);
137 if (npos == wm.size()) {
139 const Eigen::VectorXd scale = wm.cwiseSqrt();
140 rows(m, [&](
const Eigen::Ref<const Eigen::MatrixXd>& R) {
141 Xp_m.noalias() = scale.asDiagonal() * R;
145 std::vector<Index> pos_rows;
146 std::vector<Index> neg_rows;
147 pos_rows.reserve(std::size_t(npos));
148 neg_rows.reserve(std::size_t(nneg));
149 for (
Index r = 0; r < wm.size(); ++r) {
151 pos_rows.push_back(r);
152 }
else if (wm(r) < 0.0) {
153 neg_rows.push_back(r);
156 Eigen::VectorXd pos_scale(npos);
157 Eigen::VectorXd neg_scale(nneg);
158 for (
Index i = 0; i < npos; ++i) {
159 pos_scale(i) = std::sqrt(wm(pos_rows[std::size_t(i)]));
161 for (
Index i = 0; i < nneg; ++i) {
162 neg_scale(i) = std::sqrt(-wm(neg_rows[std::size_t(i)]));
164 rows(m, [&](
const Eigen::Ref<const Eigen::MatrixXd>& R) {
165 for (
Index c = 0; c < ncols; ++c) {
166 for (
Index i = 0; i < npos; ++i) {
167 Xp_m(i, c) = pos_scale(i) * R(pos_rows[std::size_t(i)], c);
169 for (
Index i = 0; i < nneg; ++i) {
170 Xn_m(i, c) = neg_scale(i) * R(neg_rows[std::size_t(i)], c);
175#if defined(EIGEN_USE_MKL_ALL)
179 S.selfadjointView<Eigen::Lower>().rankUpdate(Xp.transpose(), 1.0);
182 S.selfadjointView<Eigen::Lower>().rankUpdate(Xn.transpose(), -1.0);
188 AccumulateTiles(
S, Xp, Xn, bs, tiles);
191 S.triangularView<Eigen::StrictlyUpper>() =
S.transpose();
197 const char jobz = vectors ?
'V' :
'N';
199 auto finish = [&](Eigen::MatrixXd& work) {
201 result.
vectors = std::move(work);
205 Eigen::MatrixXd work = A;
206 result.
values.resize(A.rows());
208 long(work.outerStride()),
209 result.
values.data()) == 0) {
214#if defined(EIGEN_USE_MKL_ALL) || defined(EIGEN_USE_LAPACKE)
215 const lapack_int n =
static_cast<lapack_int
>(A.rows());
217 Eigen::MatrixXd work = A;
218 result.
values.resize(A.rows());
219 const lapack_int info = LAPACKE_dsyevd(
220 LAPACK_COL_MAJOR, jobz,
'L', n, work.data(),
221 static_cast<lapack_int
>(work.outerStride()), result.
values.data());
228 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> es(
229 A, vectors ? Eigen::ComputeEigenvectors : Eigen::EigenvaluesOnly);
230 result.
values = es.eigenvalues();
232 result.
vectors = es.eigenvectors();
279 Eigen::MatrixXd inv = A;
280 const long n = long(A.rows());
281 const long lda = long(inv.outerStride());
284 inv.triangularView<Eigen::StrictlyUpper>() = inv.transpose();
287 return A.partialPivLu().inverse();
289#if defined(EIGEN_USE_MKL_ALL) || defined(EIGEN_USE_LAPACKE)
290 const lapack_int n =
static_cast<lapack_int
>(A.rows());
291 Eigen::MatrixXd inv = A;
295 const lapack_int lda =
static_cast<lapack_int
>(inv.outerStride());
296 if (LAPACKE_dpotrf(LAPACK_COL_MAJOR,
'L', n, inv.data(), lda) == 0 &&
297 LAPACKE_dpotri(LAPACK_COL_MAJOR,
'L', n, inv.data(), lda) == 0) {
298 inv.triangularView<Eigen::StrictlyUpper>() = inv.transpose();
302 Eigen::LLT<Eigen::MatrixXd> llt(A);
303 if (llt.info() == Eigen::Success) {
306 Eigen::MatrixXd inv =
307 llt.solve(Eigen::MatrixXd::Identity(A.rows(), A.cols()));
308 inv.triangularView<Eigen::StrictlyUpper>() = inv.transpose();
312 return A.partialPivLu().inverse();