5#ifndef PROXSUITE_LINALG_DENSE_LDLT_LDLT_HPP
6#define PROXSUITE_LINALG_DENSE_LDLT_LDLT_HPP
35#ifdef PROXSUITE_VECTORIZE
36 static constexpr usize min_align =
alignof(std::max_align_t) >
39 :
alignof(std::max_align_t);
41 static constexpr usize min_align = 0;
49 if (l.align < min_align) {
168 static constexpr auto DYN = Eigen::Dynamic;
169 using ColMat = Eigen::Matrix<T, DYN, DYN, Eigen::ColMajor>;
170 using RowMat = Eigen::Matrix<T, DYN, DYN, Eigen::RowMajor>;
171 using Vec = Eigen::Matrix<T, DYN, 1>;
173 using LView = Eigen::TriangularView<Eigen::Map<
176 Eigen::OuterStride<DYN>>,
178 using LViewMut = Eigen::TriangularView<Eigen::Map<
181 Eigen::OuterStride<DYN>>,
184 using LTView = Eigen::TriangularView<Eigen::Map<
187 Eigen::OuterStride<DYN>>,
189 using LTViewMut = Eigen::TriangularView<Eigen::Map<
192 Eigen::OuterStride<DYN>>,
196 Eigen::Map<Vec const, Eigen::Unaligned, Eigen::InnerStride<DYN>>;
197 using DViewMut = Eigen::Map<Vec, Eigen::Unaligned, Eigen::InnerStride<DYN>>;
199 using VecMapISize = Eigen::Map<Eigen::Matrix<isize, DYN, 1>
const>;
200 using Perm = Eigen::PermutationWrapper<VecMapISize>;
217 VEG_REFLECT(
Ldlt, ld_storage, stride, perm, perm_inv, maybe_sorted_diag);
219 static auto adjusted_stride(isize n)
noexcept -> isize
221 return _detail::adjusted_stride<T>(n);
243 static_assert(
VEG_CONCEPT(nothrow_constructible<T>),
".");
245 auto new_stride = adjusted_stride(cap);
246 if (cap <= stride && cap * new_stride <= ld_storage.
len()) {
251 perm.reserve_exact(cap);
252 perm_inv.reserve_exact(cap);
253 maybe_sorted_diag.reserve_exact(cap);
255 ld_storage.resize_for_overwrite(cap * new_stride);
268 auto new_stride = adjusted_stride(cap);
269 if (cap <= stride && cap * new_stride <= ld_storage.
len()) {
275 perm.reserve_exact(cap);
276 perm_inv.reserve_exact(cap);
277 maybe_sorted_diag.reserve_exact(cap);
279 ld_storage.resize_for_overwrite(cap * new_stride);
281 for (isize i = 0; i < n; ++i) {
282 auto col = n - i - 1;
286 ptr + col * stride + n,
287 ptr + col * new_stride + n);
303 _detail::adjusted_stride<T>(n) * r * isize{
sizeof(T) },
307 r * isize{
sizeof(T) },
310 return w_req & alpha_req;
324 r * isize{
sizeof(isize) },
348 VEG_ASSERT(std::is_sorted(indices, indices + r));
352 auto _indices_actual =
354 auto* indices_actual = _indices_actual.
ptr_mut();
356 for (isize k = 0; k < r; ++k) {
357 indices_actual[k] = perm_inv[indices[k]];
367 for (isize k = 0; k < r; ++k) {
368 auto i_actual = indices_actual[r - 1 - k];
369 auto i = indices[r - 1 - k];
371 perm.pop_mid(i_actual);
373 maybe_sorted_diag.pop_mid(i_actual);
375 for (isize j = 0; j < n - 1 - k; ++j) {
377 auto& pinv_j = perm_inv[j];
382 if (pinv_j > i_actual) {
392 auto diag_elem = a[i];
395 for (; pos < n; ++pos) {
396 if (diag_elem >= maybe_sorted_diag[pos]) {
415 isize{
sizeof(T) } * (adjusted_stride(n + r) * r),
432 Eigen::Ref<ColMat const> a,
447 for (isize j = 0; j < n; ++j) {
449 auto& pinv_j = perm_inv[j];
454 if (pinv_j >= i_actual) {
459 for (isize k = 0; k < r; ++k) {
460 perm.push_mid(i + k, i_actual + k);
461 perm_inv.push_mid(i_actual + k, i + k);
462 maybe_sorted_diag.push_mid(a(i + k, k), i_actual + k);
467 for (isize k = 0; k < r; ++k) {
468 for (isize j = 0; j < n + r; ++j) {
469 permuted_a(j, k) = a(perm[j], k);
488 auto algo_req = StackReq{
489 2 * r * isize{
sizeof(isize) },
492 auto w_req = StackReq{
493 _detail::adjusted_stride<T>(n) * r * isize{
sizeof(T) },
496 auto alpha_req = StackReq{
497 r * isize{
sizeof(T) },
500 return algo_req & w_req & alpha_req;
519 Eigen::Ref<Vec const> alpha,
529 auto _sorted_indices =
531 auto* positions = _positions.
ptr_mut();
532 auto* sorted_indices = _sorted_indices.ptr_mut();
534 for (isize k = 0; k < r; ++k) {
535 indices[k] = perm_inv[indices[k]];
540 positions, positions + r, [indices](isize i, isize j)
noexcept ->
bool {
541 return indices[i] < indices[j];
544 for (isize k = 0; k < r; ++k) {
545 sorted_indices[k] = indices[positions[k]];
548 auto first = sorted_indices[0];
549 auto n =
dim() - first;
554 for (isize k = 0; k < r; ++k) {
555 _alpha(k) = alpha(positions[k]);
556 _w(sorted_indices[k] - first, k) = 1;
581 Eigen::Ref<ColMat const> w,
582 Eigen::Ref<Vec const> alpha,
597 for (isize k = 0; k < r; ++k) {
598 auto alpha_tmp = alpha(k);
599 _alpha(k) = alpha_tmp;
600 for (isize i = 0; i < n; ++i) {
601 auto w_tmp = w(perm[i], k);
603 maybe_sorted_diag[i] += alpha_tmp * (w_tmp * w_tmp);
614 auto dim() const noexcept -> isize {
return perm.len(); }
619 Eigen::OuterStride<DYN>>
621 return { ld_storage.
ptr(),
dim(),
dim(), stride };
626 Eigen::OuterStride<DYN>>
633 Eigen::OuterStride<DYN>>
639 Eigen::OuterStride<DYN>{ stride },
645 Eigen::OuterStride<DYN>>
651 Eigen::OuterStride<DYN>{ stride },
655 auto l() const noexcept -> LView
657 return ld_col().template triangularView<Eigen::UnitLower>();
661 return ld_col_mut().template triangularView<Eigen::UnitLower>();
663 auto lt() const noexcept -> LTView
665 return ld_row().template triangularView<Eigen::UnitUpper>();
669 return ld_row_mut().template triangularView<Eigen::UnitUpper>();
672 auto d() const noexcept -> DView
678 Eigen::InnerStride<DYN>{ stride + 1 },
687 Eigen::InnerStride<DYN>{ stride + 1 },
690 auto p() const -> Perm {
return { VecMapISize(perm.ptr(),
dim()) }; }
691 auto pt() const -> Perm {
return { VecMapISize(perm_inv.ptr(),
dim()) }; }
703 n * adjusted_stride(n) * isize{
sizeof(T) },
722 isize n = mat.rows();
725 perm.resize_for_overwrite(n);
726 perm_inv.resize_for_overwrite(n);
727 maybe_sorted_diag.resize_for_overwrite(n);
740 for (isize i = 0; i < n; ++i) {
741 maybe_sorted_diag[i] =
ld_col()(i, i);
756 n * isize{
sizeof(T) },
770 isize n = rhs.rows();
773 for (isize i = 0; i < n; ++i) {
774 work[i] = rhs[perm[i]];
779 for (isize i = 0; i < n; ++i) {
780 rhs[i] = work[perm_inv[i]];
789 isize m = rhs.rows();
792 for (isize i = 0; i < m; ++i) {
793 work[i] = rhs[perm[n + i] -
797 for (isize i = 0; i < m; ++i) {
798 rhs[i] = work[perm_inv[n + i] - n];
805 auto tmp = ColMat(n, n);
807 tmp = tmp *
d().asDiagonal();
808 auto A = ColMat(tmp *
lt());
815 auto tmp = ColMat(n, n);
817 tmp = tmp *
d().asDiagonal();
818 auto A = ColMat(tmp *
lt());
820 for (isize i = 0; i < n; i++) {
821 tmp.row(i) = A.row(perm_inv[i]);
823 for (isize i = 0; i < n; i++) {
824 A.col(i) = tmp.col(perm_inv[i]);
#define LDLT_TEMP_MAT_UNINIT(Type, Name, Rows, Cols, Stack)
#define LDLT_TEMP_VEC_UNINIT(Type, Name, Rows, Stack)
#define LDLT_TEMP_MAT(Type, Name, Rows, Cols, Stack)
#define VEG_REFLECT(PClass,...)
void apply_permutation_tri_lower(Mat &&mat, Work &&work, isize const *perm_indices)
VEG_NO_INLINE void compute_permutation(isize *perm_indices, isize *perm_inv_indices, Diag const &diagonal)
void rank_r_update_clobber_w_impl(LD ld, T *pw, isize w_stride, T *palpha, Fn r_fn)
auto diagonal(Mat &&mat) noexcept -> Eigen::Map< _detail::const_if< _detail::ptr_is_const< decltype(mat.data())>::value, Eigen::Matrix< typename proxsuite::linalg::veg::uncvref_t< Mat >::Scalar, Eigen::Dynamic, 1, Eigen::ColMajor > >, Eigen::Unaligned, Eigen::InnerStride< Eigen::Dynamic > >
auto submatrix(Mat &&mat, isize row_start, isize col_start, isize nrows, isize ncols) noexcept -> Eigen::Map< _detail::const_if< _detail::ptr_is_const< decltype(mat.data())>::value, _detail::OwnedMatrix< proxsuite::linalg::veg::uncvref_t< Mat > > >, Eigen::Unaligned, _detail::StrideOf< proxsuite::linalg::veg::uncvref_t< Mat > > >
auto ldlt_insert_rows_and_cols_req(proxsuite::linalg::veg::Tag< T > tag, isize n, isize r) noexcept -> proxsuite::linalg::veg::dynstack::StackReq
void ldlt_delete_rows_and_cols_sort_indices(Mat &&ld, isize *indices, isize r, proxsuite::linalg::veg::dynstack::DynStackMut stack)
void ldlt_insert_rows_and_cols(Mat &&ld, isize pos, A_1 const &a_1, proxsuite::linalg::veg::dynstack::DynStackMut stack)
void solve(Mat const &mat, Rhs &&rhs)
void rank_r_update_clobber_inputs(LD &&ld, W &&w, A &&alpha)
void factorize(Mat &&mat, proxsuite::linalg::veg::dynstack::DynStackMut stack)
auto ldlt_delete_rows_and_cols_req(proxsuite::linalg::veg::Tag< T >, isize n, isize r) noexcept -> proxsuite::linalg::veg::dynstack::StackReq
auto factorize_req(proxsuite::linalg::veg::Tag< T > tag, isize n) noexcept -> proxsuite::linalg::veg::dynstack::StackReq
decltype(sizeof(0)) usize
static auto insert_block_at_req(isize n, isize r) noexcept -> proxsuite::linalg::veg::dynstack::StackReq
static auto delete_at_req(isize n, isize r) noexcept -> proxsuite::linalg::veg::dynstack::StackReq
auto ld_col() const noexcept -> Eigen::Map< ColMat const, Eigen::Unaligned, Eigen::OuterStride< DYN > >
void reserve(isize cap) noexcept
auto dim() const noexcept -> isize
void dual_solve_in_place(Eigen::Ref< Vec > rhs, isize n, proxsuite::linalg::veg::dynstack::DynStackMut stack) const
auto l() const noexcept -> LView
auto dbg_reconstructed_matrix_internal() const -> ColMat
auto lt() const noexcept -> LTView
static auto factorize_req(isize n) -> proxsuite::linalg::veg::dynstack::StackReq
auto dbg_reconstructed_matrix() const -> ColMat
static auto solve_in_place_req(isize n) -> proxsuite::linalg::veg::dynstack::StackReq
auto choose_insertion_position(isize i, Eigen::Ref< Vec const > a) -> isize
void diagonal_update_clobber_indices(isize *indices, isize r, Eigen::Ref< Vec const > alpha, proxsuite::linalg::veg::dynstack::DynStackMut stack)
static auto rank_r_update_req(isize n, isize r) noexcept -> proxsuite::linalg::veg::dynstack::StackReq
auto d_mut() noexcept -> DViewMut
auto ld_row() const noexcept -> Eigen::Map< RowMat const, Eigen::Unaligned, Eigen::OuterStride< DYN > >
void delete_at(isize const *indices, isize r, proxsuite::linalg::veg::dynstack::DynStackMut stack)
void rank_r_update(Eigen::Ref< ColMat const > w, Eigen::Ref< Vec const > alpha, proxsuite::linalg::veg::dynstack::DynStackMut stack)
void solve_in_place(Eigen::Ref< Vec > rhs, proxsuite::linalg::veg::dynstack::DynStackMut stack) const
void insert_block_at(isize i, Eigen::Ref< ColMat const > a, proxsuite::linalg::veg::dynstack::DynStackMut stack)
auto ld_row_mut() noexcept -> Eigen::Map< RowMat, Eigen::Unaligned, Eigen::OuterStride< DYN > >
void factorize(Eigen::Ref< ColMat const > mat, proxsuite::linalg::veg::dynstack::DynStackMut stack)
auto d() const noexcept -> DView
auto l_mut() noexcept -> LViewMut
void reserve_uninit(isize cap) noexcept
auto ld_col_mut() noexcept -> Eigen::Map< ColMat, Eigen::Unaligned, Eigen::OuterStride< DYN > >
static auto diagonal_update_req(isize n, isize r) noexcept -> proxsuite::linalg::veg::dynstack::StackReq
auto lt_mut() noexcept -> LTViewMut
friend auto operator==(SimdAlignedSystemAlloc, SimdAlignedSystemAlloc) noexcept -> bool
VEG_NODISCARD VEG_INLINE auto ptr_mut() VEG_NOEXCEPT -> T *
VEG_NODISCARD VEG_INLINE auto ptr() const VEG_NOEXCEPT -> T const *
VEG_NODISCARD VEG_INLINE auto len() const VEG_NOEXCEPT -> isize
VEG_INLINE void reserve_exact(isize new_cap)
VEG_NODISCARD auto ptr_mut() const VEG_NOEXCEPT -> void *
static VEG_INLINE void dealloc(RefMut, void *ptr, Layout l) noexcept
VEG_NODISCARD static VEG_INLINE auto alloc(RefMut, Layout l) noexcept -> mem::AllocBlock
VEG_NODISCARD static VEG_INLINE auto grow(RefMut, void *ptr, Layout l, usize new_size, RelocFn reloc) noexcept -> mem::AllocBlock
VEG_NODISCARD static VEG_INLINE auto shrink(RefMut, void *ptr, Layout l, usize new_size, RelocFn reloc) noexcept -> mem::AllocBlock
static VEG_INLINE auto adjusted_layout(Layout l) noexcept -> Layout