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