aligator  0.14.0
A primal-dual augmented Lagrangian-type solver for nonlinear trajectory optimization.
 
Loading...
Searching...
No Matches
bunchkaufman.hpp
Go to the documentation of this file.
1
4#pragma once
5
6#include "Eigen/Core"
7
8namespace Eigen {
9template <typename MatrixType_, int UpLo_ = Lower> struct BunchKaufman;
10
11namespace internal {
12template <typename MatrixType_, int UpLo_>
13struct traits<BunchKaufman<MatrixType_, UpLo_>> : traits<MatrixType_> {
14 typedef MatrixXpr XprKind;
15 typedef SolverStorage StorageKind;
16 typedef int StorageIndex;
17 enum { Flags = 0 };
18};
19
20template <typename MatrixType, typename IndicesType>
21ComputationInfo bunch_kaufman_in_place_unblocked(MatrixType &a,
22 IndicesType &pivots,
23 Index &pivot_count) {
24 using Scalar = typename MatrixType::Scalar;
25 using Real = typename Eigen::NumTraits<Scalar>::Real;
26 const Real alpha = (Real(1) + numext::sqrt(Real(17))) / Real(8);
27 using std::swap;
28
29 pivot_count = 0;
30
31 const Index n = a.rows();
32 if (n == 0) {
33 return Success;
34 } else if (n == 1) {
35 if (numext::abs(numext::real(a(0, 0))) == Real(0)) {
36 return NumericalIssue;
37 } else {
38 a(0, 0) = Real(1) / numext::real(a(0, 0));
39 return Success;
40 }
41 }
42
43 Index k = 0;
44 while (k < n) {
45 Index k_step = 1;
46 Real abs_akk = numext::abs(numext::real(a(k, k)));
47 Index imax = 0;
48 Real colmax = Real(0);
49
50 if (k + 1 < n) {
51 colmax = a.col(k).segment(k + 1, n - k - 1).cwiseAbs().maxCoeff(&imax);
52 }
53 imax += k + 1;
54
55 Index kp;
56 if (numext::maxi(abs_akk, colmax) == Real(0)) {
57 return NumericalIssue;
58 } else {
59 if (abs_akk >= colmax * alpha) {
60 kp = k;
61 } else {
62 Real rowmax = Real(0);
63 if (imax - k > 0) {
64 rowmax = a.row(imax).segment(k, imax - k).cwiseAbs().maxCoeff();
65 }
66 if (n - imax - 1 > 0) {
67 rowmax = numext::maxi(rowmax, a.col(imax)
68 .segment(imax + 1, n - imax - 1)
69 .cwiseAbs()
70 .maxCoeff());
71 }
72
73 if (abs_akk >= (alpha * colmax) * (colmax / rowmax)) {
74 kp = k;
75 } else if (numext::abs(numext::real(a(imax, imax))) >= alpha * rowmax) {
76 kp = imax;
77 } else {
78 kp = imax;
79 k_step = 2;
80 }
81 }
82
83 Index kk = k + k_step - 1;
84 if (kp != kk) {
85 pivot_count += 1;
86 a.col(kk)
87 .segment(kp + 1, n - kp - 1)
88 .swap(a.col(kp).segment(kp + 1, n - kp - 1));
89
90 for (Index j = kk + 1; j < kp; ++j) {
91 Scalar tmp = a(j, kk);
92 a(j, kk) = numext::conj(a(kp, j));
93 a(kp, j) = numext::conj(tmp);
94 }
95 a(kp, kk) = numext::conj(a(kp, kk));
96 swap(a(kk, kk), a(kp, kp));
97
98 if (k_step == 2) {
99 swap(a(k + 1, k), a(kp, k));
100 }
101 }
102
103 if (k_step == 1) {
104 Real d11 = Real(1) / numext::real(a(k, k));
105 a(k, k) = Scalar(d11);
106
107 auto x = a.middleRows(k + 1, n - k - 1).col(k);
108 auto trailing =
109 a.middleRows(k + 1, n - k - 1).middleCols(k + 1, n - k - 1);
110
111 for (Index j = 0; j < n - k - 1; ++j) {
112 Scalar d11xj = numext::conj(x(j)) * d11;
113 for (Index i = j; i < n - k - 1; ++i) {
114 Scalar xi = x(i);
115 trailing(i, j) -= d11xj * xi;
116 }
117 trailing(j, j) = Scalar(numext::real(trailing(j, j)));
118 }
119
120 x *= d11;
121 } else {
122 Real d21_abs = numext::abs(a(k + 1, k));
123 Real d21_inv = Real(1) / d21_abs;
124 Real d11 = d21_inv * numext::real(a(k + 1, k + 1));
125 Real d22 = d21_inv * numext::real(a(k, k));
126
127 Real t = Real(1) / ((d11 * d22) - Real(1));
128 Real d = t * d21_inv;
129 Scalar d21 = a(k + 1, k) * d21_inv;
130
131 a(k, k) = Scalar(d11 * d);
132 a(k + 1, k) = -d21 * d;
133 a(k + 1, k + 1) = Scalar(d22 * d);
134
135 for (Index j = k + 2; j < n; ++j) {
136 Scalar wk = ((a(j, k) * d11) - (a(j, k + 1) * d21)) * d;
137 Scalar wkp1 =
138 ((a(j, k + 1) * d22) - (a(j, k) * numext::conj(d21))) * d;
139
140 for (Index i = j; i < n; ++i) {
141 a(i, j) -=
142 a(i, k) * numext::conj(wk) + a(i, k + 1) * numext::conj(wkp1);
143 }
144 a(j, j) = Scalar(numext::real(a(j, j)));
145
146 a(j, k) = wk;
147 a(j, k + 1) = wkp1;
148 }
149 }
150 }
151
152 // pivots matrix store int by default
153 // Like Eigen, we assume that we will never
154 // have a matrix that will have more rows/columns
155 // than int can old
156 if (k_step == 1) {
157 pivots[k] = static_cast<int>(kp);
158 } else {
159 pivots[k] = static_cast<int>(-1 - kp);
160 pivots[k + 1] = static_cast<int>(-1 - kp);
161 }
162
163 k += k_step;
164 }
165
166 return Success;
167}
168
169template <typename MatrixType, typename WType, typename IndicesType>
170ComputationInfo
171bunch_kaufman_in_place_one_block(MatrixType &a, WType &w, IndicesType &pivots,
172 Index &pivot_count, Index &processed_cols) {
173 using Scalar = typename MatrixType::Scalar;
174 using Real = typename Eigen::NumTraits<Scalar>::Real;
175
176 pivot_count = 0;
177 processed_cols = 0;
178 Real alpha = (Real(1) + numext::sqrt(Real(17))) / Real(8);
179
180 Index n = a.rows();
181 if (n == 0) {
182 return Success;
183 }
184
185 Index nb = w.cols();
186 Index k = 0;
187 while (k < n && k + 1 < nb) {
188 w.col(k).segment(k, n - k) = a.col(k).segment(k, n - k);
189 {
190 auto w_row = w.row(k).segment(0, k);
191 auto w_col = w.col(k).segment(k, n - k);
192 w_col.noalias() -= a.block(k, 0, n - k, k) * w_row.transpose();
193 }
194 w(k, k) = Scalar(numext::real(w(k, k)));
195
196 Index k_step = 1;
197 Real abs_akk = numext::abs(numext::real(w(k, k)));
198 Index imax = 0;
199 Real colmax = Real(0);
200
201 if (k + 1 < n) {
202 colmax = w.col(k).segment(k + 1, n - k - 1).cwiseAbs().maxCoeff(&imax);
203 }
204 imax += k + 1;
205
206 Index kp;
207 if (numext::maxi(abs_akk, colmax) == Real(0)) {
208 return NumericalIssue;
209 } else {
210 if (abs_akk >= colmax * alpha) {
211 kp = k;
212 } else {
213 w.col(k + 1).segment(k, imax - k) =
214 a.row(imax).segment(k, imax - k).adjoint();
215 w.col(k + 1).segment(imax, n - imax) =
216 a.col(imax).segment(imax, n - imax);
217
218 {
219 auto w_row = w.row(imax).segment(0, k);
220 auto w_col = w.col(k + 1).segment(k, n - k);
221 w_col.noalias() -= a.block(k, 0, n - k, k) * w_row.transpose();
222 }
223 w(imax, k + 1) = Scalar(numext::real(w(imax, k + 1)));
224
225 Real rowmax = Real(0);
226 if (imax - k > 0) {
227 rowmax = w.col(k + 1).segment(k, imax - k).cwiseAbs().maxCoeff();
228 }
229 if (n - imax - 1 > 0) {
230 rowmax = numext::maxi(rowmax, w.col(k + 1)
231 .segment(imax + 1, n - imax - 1)
232 .cwiseAbs()
233 .maxCoeff());
234 }
235
236 if (abs_akk >= (alpha * colmax) * (colmax / rowmax)) {
237 kp = k;
238 } else if (numext::abs(numext::real(w(imax, k + 1))) >=
239 alpha * rowmax) {
240 kp = imax;
241 w.col(k).segment(k, n - k) = w.col(k + 1).segment(k, n - k);
242 } else {
243 kp = imax;
244 k_step = 2;
245 }
246 }
247
248 Index kk = k + k_step - 1;
249 if (kp != kk) {
250 pivot_count += 1;
251
252 a(kp, kp) = a(kk, kk);
253 for (Index j = kk + 1; j < kp; ++j) {
254 a(kp, j) = numext::conj(a(j, kk));
255 }
256 a.col(kp).segment(kp + 1, n - kp - 1) =
257 a.col(kk).segment(kp + 1, n - kp - 1);
258 a.row(kk).segment(0, k).swap(a.row(kp).segment(0, k));
259 w.row(kk).segment(0, kk + 1).swap(w.row(kp).segment(0, kk + 1));
260 }
261
262 if (k_step == 1) {
263 a.col(k).segment(k, n - k) = w.col(k).segment(k, n - k);
264
265 Real d11 = Real(1) / numext::real(w(k, k));
266 a(k, k) = Scalar(d11);
267 auto x = a.middleRows(k + 1, n - k - 1).col(k);
268 x *= d11;
269 w.col(k).segment(k + 1, n - k - 1) =
270 w.col(k).segment(k + 1, n - k - 1).conjugate();
271 } else {
272 Real d21_abs = numext::abs(w(k + 1, k));
273 Real d21_inv = Real(1) / d21_abs;
274 Real d11 = d21_inv * numext::real(w(k + 1, k + 1));
275 Real d22 = d21_inv * numext::real(w(k, k));
276
277 Real t = Real(1) / ((d11 * d22) - Real(1));
278 Scalar d21 = w(k + 1, k) * d21_inv;
279 Real d = t * d21_inv;
280
281 a(k, k) = Scalar(d11 * d);
282 a(k + 1, k) = -d21 * d;
283 a(k + 1, k + 1) = Scalar(d22 * d);
284
285 for (Index j = k + 2; j < n; ++j) {
286 Scalar wk = ((w(j, k) * d11) - (w(j, k + 1) * d21)) * d;
287 Scalar wkp1 =
288 ((w(j, k + 1) * d22) - (w(j, k) * numext::conj(d21))) * d;
289
290 a(j, k) = wk;
291 a(j, k + 1) = wkp1;
292 }
293
294 w.col(k).segment(k + 1, n - k - 1) =
295 w.col(k).segment(k + 1, n - k - 1).conjugate();
296 w.col(k + 1).segment(k + 2, n - k - 2) =
297 w.col(k + 1).segment(k + 2, n - k - 2).conjugate();
298 }
299 }
300
301 // pivots matrix store int by default
302 // Like Eigen, we assume that we will never
303 // have a matrix that will have more rows/columns
304 // than int can old
305 if (k_step == 1) {
306 pivots[k] = static_cast<int>(kp);
307 } else {
308 pivots[k] = static_cast<int>(-1 - kp);
309 pivots[k + 1] = static_cast<int>(-1 - kp);
310 }
311
312 k += k_step;
313 }
314
315 auto a_left = a.bottomRows(n - k).leftCols(k);
316 auto a_right = a.bottomRows(n - k).rightCols(n - k);
317
318 a_right.template triangularView<Lower>() -=
319 a_left * w.block(k, 0, n - k, k).transpose();
320 Index j = k - 1;
321 processed_cols = k;
322
323 while (true) {
324 Index jj = j;
325 Index jp = pivots[j];
326 if (jp < 0) {
327 jp = -1 - jp;
328 j -= 1;
329 }
330
331 if (j == 0) {
332 return Success;
333 }
334 j -= 1;
335 if (jp != jj) {
336 a.row(jp).segment(0, j + 1).swap(a.row(jj).segment(0, j + 1));
337 }
338 if (j == 0) {
339 return Success;
340 }
341 }
342}
343
344template <typename MatrixType, typename VecType, typename IndicesType,
345 typename WorkspaceType>
346ComputationInfo bunch_kaufman_in_place(MatrixType &a, VecType &subdiag,
347 IndicesType &pivots, WorkspaceType &w,
348 Index &pivot_count) {
349 Index n = a.rows();
350
351 const Index blocksize = w.cols();
352
353 Index k = 0;
354 while (k < n) {
355 Index kb = 0;
356 Index k_pivot_count = 0;
357 auto a_block = a.block(k, k, n - k, n - k);
358 auto pivots_block = pivots.segment(k, n - k);
359 ComputationInfo info = InvalidInput;
360 if (blocksize != 0 && blocksize < n - k) {
361 info = internal::bunch_kaufman_in_place_one_block(
362 a_block, w, pivots_block, k_pivot_count, kb);
363 } else {
364 info = internal::bunch_kaufman_in_place_unblocked(a_block, pivots_block,
365 k_pivot_count);
366 kb = n - k;
367 }
368 if (info != Success) {
369 return info;
370 }
371
372 for (Index j = k; j < k + kb; ++j) {
373 auto &p = pivots.coeffRef(j);
374 // pivots matrix store int by default
375 // Like Eigen, we assume that we will never
376 // have a matrix that will have more rows/columns
377 // than int can old
378 if (p >= 0) {
379 p += static_cast<int>(k);
380 } else {
381 p -= static_cast<int>(k);
382 }
383 }
384
385 pivot_count += k_pivot_count;
386 k += kb;
387 }
388
389 using Scalar = typename MatrixType::Scalar;
390
391 k = 0;
392 while (k < n) {
393 if (pivots[k] < 0) {
394 subdiag(k) = a(k + 1, k);
395 subdiag(k + 1) = Scalar(0);
396 a(k + 1, k) = Scalar(0);
397 k += 2;
398 } else {
399 subdiag(k) = Scalar(0);
400 k += 1;
401 }
402 }
403
404 k = 0;
405 while (k < n) {
406 Index p = pivots[k];
407 if (p < 0) {
408 p = -1 - p;
409 a.row(k + 1).segment(0, k).swap(a.row(p).segment(0, k));
410 k += 2;
411 } else {
412 a.row(k).segment(0, k).swap(a.row(p).segment(0, k));
413 k += 1;
414 }
415 }
416
417 return Success;
418}
419
420template <typename MatrixType, bool Conjugate> struct BK_Traits;
421
422template <typename MatrixType> struct BK_Traits<MatrixType, false> {
423 typedef TriangularView<const MatrixType, UnitLower> MatrixL;
424 typedef TriangularView<const typename MatrixType::AdjointReturnType,
425 UnitUpper>
426 MatrixU;
427 static inline MatrixL getL(const MatrixType &m) { return MatrixL(m); }
428 static inline MatrixU getU(const MatrixType &m) {
429 return MatrixU(m.adjoint());
430 }
431};
432
433template <typename MatrixType> struct BK_Traits<MatrixType, true> {
434 typedef typename MatrixType::ConjugateReturnType ConjugateReturnType;
435 typedef TriangularView<const ConjugateReturnType, UnitLower> MatrixL;
436 typedef TriangularView<const typename MatrixType::TransposeReturnType,
437 UnitUpper>
438 MatrixU;
439 static inline MatrixL getL(const MatrixType &m) {
440 return MatrixL(m.conjugate());
441 }
442 static inline MatrixU getU(const MatrixType &m) {
443 return MatrixU(m.transpose());
444 }
445};
446
447template <bool Conjugate, typename MatrixType, typename VecType,
448 typename IndicesType, typename Rhs>
449void bunch_kaufman_solve_in_place(MatrixType const &L, VecType const &subdiag,
450 IndicesType const &pivots, Rhs &x) {
451 Index n = L.rows();
452
453 Index k;
454
455 k = 0;
456 while (k < n) {
457 Index p = pivots(k);
458 if (p < 0) {
459 p = -1 - p;
460 x.row(k + 1).swap(x.row(p));
461 k += 2;
462 } else {
463 x.row(k).swap(x.row(p));
464 k += 1;
465 }
466 }
467
468 using Traits = BK_Traits<MatrixType, Conjugate>;
469
470 Traits::getL(L).solveInPlace(x);
471
472 k = 0;
473 while (k < n) {
474 Index p = pivots(k);
475 if (p < 0) {
476 using Scalar = typename MatrixType::Scalar;
477 using Real = typename Eigen::NumTraits<Scalar>::Real;
478
479 Scalar akp1k = subdiag(k);
480 Real ak = numext::real(L(k, k));
481 Real akp1 = numext::real(L(k + 1, k + 1));
482
483 if (Conjugate) {
484 akp1k = numext::conj(akp1k);
485 }
486
487 for (Index j = 0; j < x.cols(); ++j) {
488 Scalar xk = x(k, j);
489 Scalar xkp1 = x(k + 1, j);
490
491 x(k, j) = xk * ak + xkp1 * numext::conj(akp1k);
492 x(k + 1, j) = xkp1 * akp1 + xk * akp1k;
493 }
494
495 k += 2;
496 } else {
497 x.row(k) *= numext::real(L(k, k));
498 k += 1;
499 }
500 }
501
502 Traits::getU(L).solveInPlace(x);
503
504 k = n;
505 while (k > 0) {
506 k -= 1;
507 Index p = pivots(k);
508 if (p < 0) {
509 p = -1 - p;
510 x.row(k).swap(x.row(p));
511 k -= 1;
512 } else {
513 x.row(k).swap(x.row(p));
514 }
515 }
516}
517} // namespace internal
518
519template <typename MatrixType_, int UpLo_>
520struct BunchKaufman : SolverBase<BunchKaufman<MatrixType_, UpLo_>> {
521 enum {
522 MaxRowsAtCompileTime = MatrixType_::MaxRowsAtCompileTime,
523 MaxColsAtCompileTime = MatrixType_::MaxColsAtCompileTime,
524 UpLo = UpLo_
525 };
526 using MatrixType = MatrixType_;
527 using PlainObject = typename MatrixType::PlainObject;
528 using Base = SolverBase<BunchKaufman>;
529 static constexpr Index BlockSize = 32;
530 EIGEN_GENERIC_PUBLIC_INTERFACE(BunchKaufman)
531 using VecType = Matrix<Scalar, RowsAtCompileTime, 1, Eigen::DontAlign,
533 friend class SolverBase<BunchKaufman>;
534
536 typename Transpositions<RowsAtCompileTime,
539 PermutationMatrix<RowsAtCompileTime, MaxRowsAtCompileTime>;
540
542 : m_matrix()
543 , m_subdiag()
544 , m_pivot_count(0)
545 , m_pivots()
546 , m_isInitialized(false)
547 , m_info(ComputationInfo::InvalidInput)
548 , m_blocksize()
549 , m_workspace() {}
550 explicit BunchKaufman(Index size)
551 : m_matrix(size, size)
552 , m_subdiag(size)
553 , m_pivot_count(0)
554 , m_pivots(size)
555 , m_isInitialized(false)
556 , m_info(ComputationInfo::InvalidInput)
557 , m_blocksize(size <= BlockSize ? 0 : BlockSize)
558 , m_workspace(size, m_blocksize) {}
559
560 template <typename InputType>
561 explicit BunchKaufman(const EigenBase<InputType> &matrix)
562 : m_matrix(matrix.rows(), matrix.cols())
563 , m_subdiag(matrix.rows())
564 , m_pivot_count(0)
565 , m_pivots(matrix.rows())
566 , m_isInitialized(false)
567 , m_info(ComputationInfo::InvalidInput)
568 , m_blocksize(matrix.rows() <= BlockSize ? 0 : BlockSize)
569 , m_workspace(matrix.rows(), m_blocksize) {
570 this->compute(matrix.derived());
571 }
572
573 // EIGEN_DEVICE_FUNC inline EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT
574 // { return m_matrix.rows(); }
575 EIGEN_DEVICE_FUNC inline Index rows() const EIGEN_NOEXCEPT {
576 return m_matrix.rows();
577 }
578 // EIGEN_DEVICE_FUNC inline EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT
579 // { return m_matrix.cols(); }
580 EIGEN_DEVICE_FUNC inline Index cols() const EIGEN_NOEXCEPT {
581 return m_matrix.cols();
582 }
583
584 inline const MatrixType &matrixLDLT() const { return m_matrix; }
585
586 inline const IndicesType &pivots() const { return m_pivots; }
587
588 inline const VecType &subdiag() const { return m_subdiag; }
589
590 template <typename InputType>
591 BunchKaufman &compute(const EigenBase<InputType> &matrix);
592
593 ComputationInfo info() const { return m_info; }
594
595#ifdef EIGEN_PARSED_BY_DOXYGEN
596 template <typename Rhs>
597 inline const Solve<LDLT, Rhs> solve(const MatrixBase<Rhs> &b) const;
598#endif
599
600#ifndef EIGEN_PARSED_BY_DOXYGEN
601 template <typename RhsType, typename DstType>
602 void _solve_impl(const RhsType &rhs, DstType &dst) const;
603
604 template <bool Conjugate, typename RhsType, typename DstType>
605 void _solve_impl_transposed(const RhsType &rhs, DstType &dst) const;
606
607 template <typename RhsType>
608 bool solveInPlace(Eigen::MatrixBase<RhsType> &bAndX) const;
609#endif
610
611private:
612 MatrixType m_matrix;
613 VecType m_subdiag;
614 Index m_pivot_count;
615 IndicesType m_pivots;
616 bool m_isInitialized;
617 ComputationInfo m_info;
618 Index m_blocksize;
619 PlainObject m_workspace;
620};
621
622#ifndef EIGEN_PARSED_BY_DOXYGEN
623template <typename MatrixType_, int UpLo_>
624template <typename RhsType, typename DstType>
626 DstType &dst) const {
627 dst = rhs;
628 internal::bunch_kaufman_solve_in_place<false>(this->m_matrix, this->m_subdiag,
629 this->m_pivots, dst);
630}
631
632template <typename MatrixType_, int UpLo_>
633template <bool Conjugate, typename RhsType, typename DstType>
635 const RhsType &rhs, DstType &dst) const {
636 dst = rhs;
637 internal::bunch_kaufman_solve_in_place<!Conjugate>(
638 this->m_matrix, this->m_subdiag, this->m_pivots, dst);
639}
640
641template <typename MatrixType_, int UpLo_>
642template <typename RhsType>
644 Eigen::MatrixBase<RhsType> &bAndX) const {
645 bAndX = this->solve(bAndX);
646
647 return true;
648}
649#endif
650
651template <typename MatrixType_, int UpLo_>
652template <typename InputType>
654BunchKaufman<MatrixType_, UpLo_>::compute(const EigenBase<InputType> &a) {
655 eigen_assert(a.rows() == a.cols());
656 Index n = a.rows();
657 this->m_matrix.resize(n, n);
658 this->m_subdiag.resize(n);
659 this->m_pivots.resize(n);
660
661 this->m_matrix.setZero();
662 this->m_subdiag.setZero();
663 this->m_pivots.setZero();
664 this->m_blocksize = n <= BlockSize ? 0 : BlockSize;
665 this->m_workspace.setZero(n, this->m_blocksize);
666
667 this->m_matrix.template triangularView<Lower>() =
668 a.derived().template triangularView<UpLo_>();
669 this->m_info = internal::bunch_kaufman_in_place(
670 this->m_matrix, this->m_subdiag, this->m_pivots, this->m_workspace,
671 this->m_pivot_count);
672 this->m_isInitialized = true;
673 return *this;
674}
675} // namespace Eigen
676
677namespace aligator {
679}
Main package namespace.
typename Transpositions< RowsAtCompileTime, MaxRowsAtCompileTime >::IndicesType IndicesType
EIGEN_DEVICE_FUNC Index cols() const EIGEN_NOEXCEPT
SolverBase< BunchKaufman > Base
static constexpr Index BlockSize
typename MatrixType::PlainObject PlainObject
const MatrixType & matrixLDLT() const
void _solve_impl_transposed(const RhsType &rhs, DstType &dst) const
BunchKaufman(const EigenBase< InputType > &matrix)
const IndicesType & pivots() const
void _solve_impl(const RhsType &rhs, DstType &dst) const
const VecType & subdiag() const
bool solveInPlace(Eigen::MatrixBase< RhsType > &bAndX) const
EIGEN_DEVICE_FUNC Index rows() const EIGEN_NOEXCEPT
ComputationInfo info() const
BunchKaufman & compute(const EigenBase< InputType > &matrix)
PermutationMatrix< RowsAtCompileTime, MaxRowsAtCompileTime > PermutationType
Matrix< Scalar, RowsAtCompileTime, 1, Eigen::DontAlign, MaxRowsAtCompileTime > VecType
typename Transpositions< RowsAtCompileTime, MaxRowsAtCompileTime >::IndicesType IndicesType
static constexpr Index BlockSize
typename MatrixType::PlainObject PlainObject
void _solve_impl_transposed(const RhsType &rhs, DstType &dst) const
void _solve_impl(const RhsType &rhs, DstType &dst) const
bool solveInPlace(Eigen::MatrixBase< RhsType > &bAndX) const
Matrix< Scalar, RowsAtCompileTime, 1, Eigen::DontAlign, MaxRowsAtCompileTime > VecType