.. _program_listing_file__tmp_ws_src_proxsuite_include_proxsuite_proxqp_dense_views.hpp: Program Listing for File views.hpp ================================== |exhale_lsh| :ref:`Return to documentation for file ` (``/tmp/ws/src/proxsuite/include/proxsuite/proxqp/dense/views.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp // // Copyright (c) 2022 INRIA // #ifndef PROXSUITE_PROXQP_DENSE_VIEWS_HPP #define PROXSUITE_PROXQP_DENSE_VIEWS_HPP #include #include #include #include #include #define LDLT_CONCEPT(...) \ VEG_CONCEPT_MACRO(::proxsuite::proxqp::concepts, __VA_ARGS__) #define LDLT_CHECK_CONCEPT(...) \ VEG_CHECK_CONCEPT_MACRO(::proxqp::concepts, __VA_ARGS__) namespace proxsuite { namespace proxqp { using usize = decltype(sizeof(0)); namespace detail { template struct FnInfo; template struct FnInfoRet_> { template using Arg = proxsuite::linalg::veg::ith; using Ret = Ret_; }; } // namespace detail #define LDLT_IMPL_GET_PARAM(Fn, Idx) \ typename ::proxsuite::proxqp::detail::FnInfo< \ decltype Fn /* NOLINT */>::template Arg<(Idx)>, #define LDLT_IMPL_GET_PARAMS_0(NParams, ...) \ __VEG_PP_TUPLE_FOR_EACH(LDLT_IMPL_GET_PARAM, \ (__VA_ARGS__), \ __VEG_PP_MAKE_TUPLE(__VEG_IMPL_PP_DEC(NParams))) #define LDLT_IMPL_GET_PARAMS_1(NParams, ...) #define LDLT_IMPL_GET_PARAMS(NParams, ...) \ __VEG_PP_CAT2(LDLT_IMPL_GET_PARAMS_, __VEG_IMPL_PP_IS_1(NParams)) \ (NParams, __VA_ARGS__) #define LDLT_EXPLICIT_TPL_DEF(NParams, ...) \ template auto __VA_ARGS__( \ LDLT_IMPL_GET_PARAMS(NParams, __VA_ARGS__) \ typename ::proxsuite::proxqp::detail::FnInfo< \ decltype(__VA_ARGS__)>::template Arg<(NParams)-1>) \ ->typename ::proxsuite::proxqp::detail::FnInfo::Ret #define LDLT_EXPLICIT_TPL_DECL(NParams, ...) \ extern LDLT_EXPLICIT_TPL_DEF(NParams, __VA_ARGS__) using proxsuite::linalg::veg::i32; using proxsuite::linalg::veg::i64; using proxsuite::linalg::veg::isize; using proxsuite::linalg::veg::u32; using proxsuite::linalg::veg::u64; using proxsuite::linalg::veg::usize; using f32 = float; using f64 = double; namespace detail { struct NoCopy { NoCopy() = default; ~NoCopy() = default; NoCopy(NoCopy const&) = delete; NoCopy(NoCopy&&) = delete; auto operator=(NoCopy const&) -> NoCopy& = delete; auto operator=(NoCopy&&) -> NoCopy& = delete; }; template struct Defer /* NOLINT */ { Fn fn; NoCopy _; VEG_INLINE ~Defer() noexcept(noexcept(VEG_FWD(fn)())) { VEG_FWD(fn)(); } }; namespace nb { struct defer { template VEG_INLINE constexpr auto operator()(Fn fn) const -> Defer { return { VEG_FWD(fn), {} }; } }; struct max2 { template VEG_INLINE constexpr auto operator()(T const& a, T const& b) const -> T const& { return a > b ? a : b; } }; struct min2 { template VEG_INLINE constexpr auto operator()(T a, T b) const -> T { return (a < b) ? a : b; } }; } // namespace nb template constexpr auto min_list_impl(T init, T const* arr, usize n) noexcept -> T { return (n == 0) ? init : nb::min2{}(init, detail::min_list_impl(*arr, arr + 1, n - 1)); } template constexpr auto cx_min_list(T const (&arr)[N]) noexcept -> T { return detail::min_list_impl( // arr[0], arr + 1, N - 1); } namespace nb { struct max_list { template VEG_INLINE auto operator()(std::initializer_list list) const -> T { T const* data = list.begin(); isize len = isize(list.size()); T current_max = data[0]; for (isize i = 1; i < len; ++i) { if (data[i] > current_max) { current_max = data[i]; } } return current_max; } }; } // namespace nb VEG_NIEBLOID(defer); VEG_NIEBLOID(max2); VEG_NIEBLOID(min2); VEG_NIEBLOID(max_list); template::value> struct SetZeroImpl { static void fn(T* dest, usize n) { for (usize i = 0; i < n; ++i) { *dest = 0; } } }; template struct SetZeroImpl { static void fn(T* dest, usize n) { // TODO: assert bit representation is zero std::memset(dest, 0, n * sizeof(T)); } }; template void set_zero(T* dest, usize n) { SetZeroImpl::fn(dest, n); } constexpr auto round_up(isize n, isize k) noexcept -> isize { return (n + k - 1) / k * k; } constexpr auto uround_up(usize n, usize k) noexcept -> usize { return (n + k - 1) / k * k; } inline auto bytes_to_prev_aligned(void* ptr, usize align) noexcept -> isize { using UPtr = std::uintptr_t; UPtr mask = align - 1; UPtr iptr = UPtr(ptr); UPtr aligned_ptr = iptr & ~mask; return isize(aligned_ptr - iptr); } inline auto bytes_to_next_aligned(void* ptr, usize align) noexcept -> isize { using UPtr = std::uintptr_t; UPtr mask = align - 1; UPtr iptr = UPtr(ptr); UPtr aligned_ptr = (iptr + mask) & ~mask; return isize(aligned_ptr - iptr); } inline auto next_aligned(void* ptr, usize align) noexcept -> void* { using BytePtr = unsigned char*; using VoidPtr = void*; return VoidPtr(BytePtr(ptr) + detail::bytes_to_next_aligned(ptr, align)); } inline auto prev_aligned(void* ptr, usize align) noexcept -> void* { using BytePtr = unsigned char*; using VoidPtr = void*; return VoidPtr(BytePtr(ptr) + detail::bytes_to_prev_aligned(ptr, align)); } } // namespace detail enum struct Layout : unsigned char { colmajor = 0, rowmajor = 1, }; constexpr Layout colmajor = Layout::colmajor; constexpr Layout rowmajor = Layout::rowmajor; constexpr auto flip_layout(Layout l) noexcept -> Layout { return Layout(1 - u32(l)); } constexpr auto to_eigen_layout(Layout l) -> int { return l == colmajor ? Eigen::ColMajor : Eigen::RowMajor; } constexpr auto from_eigen_layout(int l) -> Layout { return (unsigned(l) & Eigen::RowMajorBit) == Eigen::RowMajor ? rowmajor : colmajor; } static_assert(to_eigen_layout(from_eigen_layout(Eigen::ColMajor)) == Eigen::ColMajor, "."); static_assert(to_eigen_layout(from_eigen_layout(Eigen::RowMajor)) == Eigen::RowMajor, "."); namespace detail { template struct ElementAccess; template<> struct ElementAccess { template VEG_INLINE static constexpr auto offset(T* ptr, isize row, isize col, isize outer_stride) noexcept -> T* { return ptr + (usize(row) + usize(col) * usize(outer_stride)); } using NextRowStride = Eigen::Stride<0, 0>; using NextColStride = Eigen::InnerStride; VEG_INLINE static auto next_row_stride(isize outer_stride) noexcept -> NextRowStride { (void)outer_stride; return NextRowStride{}; } VEG_INLINE static auto next_col_stride(isize outer_stride) noexcept -> NextColStride { return NextColStride /* NOLINT(modernize-return-braced-init-list) */ ( outer_stride); } template VEG_INLINE static void transpose_if_rowmajor(T* ptr, isize dim, isize outer_stride) { (void)ptr, (void)dim, (void)outer_stride; } }; template<> struct ElementAccess { template VEG_INLINE static constexpr auto offset(T* ptr, isize row, isize col, isize outer_stride) noexcept -> T* { return ptr + (usize(col) + usize(row) * usize(outer_stride)); } using NextColStride = Eigen::Stride<0, 0>; using NextRowStride = Eigen::InnerStride; VEG_INLINE static auto next_col_stride(isize outer_stride) noexcept -> NextColStride { (void)outer_stride; return NextColStride{}; } VEG_INLINE static auto next_row_stride(isize outer_stride) noexcept -> NextRowStride { return NextRowStride /* NOLINT(modernize-return-braced-init-list) */ ( outer_stride); } template VEG_INLINE static void transpose_if_rowmajor(T* ptr, isize dim, isize outer_stride) { Eigen::Map< // Eigen::Matrix< // T, // Eigen::Dynamic, // Eigen::Dynamic // >, // Eigen::Unaligned, // Eigen::OuterStride // >{ ptr, dim, dim, Eigen::OuterStride(outer_stride), } .transposeInPlace(); } }; } // namespace detail namespace detail { template struct unlref { using Type = T; }; template struct unlref { using Type = T; }; template auto is_eigen_matrix_base_impl(Eigen::MatrixBase const volatile*) -> proxsuite::linalg::veg::meta::true_type; auto is_eigen_matrix_base_impl(void const volatile*) -> proxsuite::linalg::veg::meta::false_type; template auto is_eigen_owning_matrix_base_impl(Eigen::PlainObjectBase const volatile*) -> proxsuite::linalg::veg::meta::true_type; auto is_eigen_owning_matrix_base_impl(void const volatile*) -> proxsuite::linalg::veg::meta::false_type; template using Void = void; template using DataExpr = decltype(static_cast(VEG_DECLVAL(Mat&).data())); template class F, typename... Ts> struct DetectedImpl : proxsuite::linalg::veg::meta::false_type { using Type = Fallback; }; template class F, typename... Ts> struct DetectedImpl>, Fallback, F, Ts...> : proxsuite::linalg::veg::meta::true_type { using Type = F; }; template class F, typename... Ts> using Detected = typename DetectedImpl::Type; template using CompTimeColsImpl = proxsuite::linalg::veg::meta::constant; template using CompTimeRowsImpl = proxsuite::linalg::veg::meta::constant; template using CompTimeInnerStrideImpl = proxsuite::linalg::veg::meta::constant; template using LayoutImpl = proxsuite::linalg::veg::meta:: constant; template using EigenMatMap = Eigen::Map< // Eigen::Matrix< // T, // Eigen::Dynamic, // Eigen::Dynamic, // (L == colmajor) // ? Eigen::ColMajor // : Eigen::RowMajor // > const, // Eigen::Unaligned, // Eigen::OuterStride // >; template using EigenMatMapMut = Eigen::Map< // Eigen::Matrix< // T, // Eigen::Dynamic, // Eigen::Dynamic, // (L == colmajor) // ? Eigen::ColMajor // : Eigen::RowMajor // >, // Eigen::Unaligned, // Eigen::OuterStride // >; template using EigenVecMap = Eigen::Map< // Eigen::Matrix< // T, // Eigen::Dynamic, // 1 // > const, // Eigen::Unaligned, // Stride // >; template using EigenVecMapMut = Eigen::Map< // Eigen::Matrix< // T, // Eigen::Dynamic, // 1 // >, // Eigen::Unaligned, // Stride // >; template using ColToVec = EigenVecMap::NextRowStride>; template using RowToVec = EigenVecMap::NextColStride>; template using ColToVecMut = EigenVecMapMut::NextRowStride>; template using RowToVecMut = EigenVecMapMut::NextColStride>; template using VecMap = EigenVecMap>; template using VecMapMut = EigenVecMapMut>; } // namespace detail template using unref = typename detail::unlref::Type; namespace eigen { template using CompTimeCols = detail::Detected, detail::CompTimeColsImpl, T>; template using CompTimeRows = detail::Detected, detail::CompTimeRowsImpl, T>; template using CompTimeInnerStride = detail::Detected, detail::CompTimeInnerStrideImpl, T>; template using GetLayout = detail::Detected(-1))>, detail::LayoutImpl, T>; } // namespace eigen namespace concepts { VEG_DEF_CONCEPT(typename T, rvalue_ref, std::is_rvalue_reference::value); VEG_DEF_CONCEPT(typename T, lvalue_ref, std::is_lvalue_reference::value); VEG_DEF_CONCEPT((template class F, typename... Ts), detected, detail::DetectedImpl::value); namespace aux { VEG_DEF_CONCEPT((typename Mat, typename T), has_data_expr, LDLT_CONCEPT(detected)); VEG_DEF_CONCEPT((typename Mat), matrix_base, decltype(detail::is_eigen_matrix_base_impl( static_cast(nullptr)))::value); VEG_DEF_CONCEPT((typename Mat), is_plain_object_base, decltype(detail::is_eigen_owning_matrix_base_impl( static_cast(nullptr)))::value); VEG_DEF_CONCEPT((typename Mat), tmp_matrix, (LDLT_CONCEPT(aux::is_plain_object_base>) && !LDLT_CONCEPT(lvalue_ref))); } // namespace aux VEG_DEF_CONCEPT((typename Mat, typename T), eigen_view, (LDLT_CONCEPT(aux::matrix_base>) && LDLT_CONCEPT(aux::has_data_expr))); VEG_DEF_CONCEPT((typename Mat, typename T), eigen_view_mut, (LDLT_CONCEPT(aux::matrix_base>) && LDLT_CONCEPT(aux::has_data_expr) && !LDLT_CONCEPT(aux::tmp_matrix))); VEG_DEF_CONCEPT((typename Mat, typename T), eigen_strided_vector_view, (LDLT_CONCEPT(eigen_view) && (eigen::CompTimeCols>::value == 1))); VEG_DEF_CONCEPT((typename Mat, typename T), eigen_strided_vector_view_mut, (LDLT_CONCEPT(eigen_view_mut) && (eigen::CompTimeCols>::value == 1))); VEG_DEF_CONCEPT((typename Mat, typename T), eigen_vector_view, (LDLT_CONCEPT(eigen_strided_vector_view) && (eigen::CompTimeInnerStride>::value == 1))); VEG_DEF_CONCEPT((typename Mat, typename T), eigen_vector_view_mut, (LDLT_CONCEPT(eigen_strided_vector_view_mut) && (eigen::CompTimeInnerStride>::value == 1))); } // namespace concepts inline namespace tags { VEG_TAG(from_ptr_size, FromPtrSize); VEG_TAG(from_ptr_size_stride, FromPtrSizeStride); VEG_TAG(from_ptr_rows_cols_stride, FromPtrRowsColsStride); VEG_TAG(from_eigen, FromEigen); } // namespace tags template struct VectorView { T const* data; isize dim; VEG_INLINE VectorView(FromPtrSize /*tag*/, T const* _data, isize _dim) noexcept : data(_data) , dim(_dim) { } VEG_TEMPLATE(typename Vec, requires(LDLT_CONCEPT(eigen_vector_view)), VEG_INLINE VectorView, (/*tag*/, FromEigen), (vec, Vec const&)) noexcept : data(vec.data()) , dim(vec.rows()) { } VEG_INLINE auto ptr(isize index) const noexcept -> T const* { return data + index; } VEG_INLINE auto operator()(isize index) const noexcept -> T const& { return *ptr(index); } VEG_INLINE auto segment(isize i, isize size) const noexcept -> VectorView { return { from_ptr_size, data + i, size, }; } VEG_INLINE auto to_eigen() const -> detail::VecMap { return detail::VecMap(data, Eigen::Index(dim)); } }; template struct VectorViewMut { T* data; isize dim; VEG_INLINE VectorViewMut(FromPtrSize /*tag*/, T* _data, isize _dim) noexcept : data(_data) , dim(_dim) { } VEG_TEMPLATE(typename Vec, requires(LDLT_CONCEPT(eigen_vector_view_mut)), VEG_INLINE VectorViewMut, (/*tag*/, FromEigen), (vec, Vec&&)) noexcept : data(vec.data()) , dim(vec.rows()) { } VEG_INLINE auto as_const() const noexcept -> VectorView { return { from_ptr_size, data, dim, }; } VEG_INLINE auto ptr(isize index) const noexcept -> T* { return data + index; } VEG_INLINE auto operator()(isize index) const noexcept -> T& { return *ptr(index); } VEG_INLINE auto segment(isize i, isize size) const noexcept -> VectorViewMut { return { from_ptr_size, data + i, size, }; } VEG_INLINE auto to_eigen() const -> detail::VecMapMut { return detail::VecMapMut(data, Eigen::Index(dim)); } }; template struct StridedVectorView { T const* data; isize dim; isize stride; VEG_INLINE StridedVectorView(FromPtrSizeStride /*tag*/, T const* _data, isize _dim, isize _stride) noexcept : data(_data) , dim(_dim) , stride(_stride) { } VEG_TEMPLATE(typename Vec, requires(LDLT_CONCEPT(eigen_strided_vector_view)), VEG_INLINE StridedVectorView, (/*tag*/, FromEigen), (vec, Vec const&)) noexcept : data(vec.data()) , dim(vec.rows()) , stride(vec.innerStride()) { } VEG_INLINE auto ptr(isize index) const noexcept -> T const* { return data + stride * index; } VEG_INLINE auto operator()(isize index) const noexcept -> T const& { return *ptr(index); } VEG_INLINE auto segment(isize i, isize size) const noexcept -> StridedVectorView { return { from_ptr_size_stride, data + stride * i, size, stride, }; } VEG_INLINE auto to_eigen() const -> detail::EigenVecMap> { return detail::EigenVecMap>( data, Eigen::Index(dim), Eigen::Index(1), Eigen::InnerStride(Eigen::Index(stride))); } }; template struct StridedVectorViewMut { T* data; isize dim; isize stride; VEG_INLINE StridedVectorViewMut(FromPtrSizeStride /*tag*/, T* _data, isize _dim, isize _stride) noexcept : data(_data) , dim(_dim) , stride(_stride) { } VEG_TEMPLATE(typename Vec, requires(LDLT_CONCEPT(eigen_strided_vector_view_mut)), VEG_INLINE StridedVectorViewMut, (/*tag*/, FromEigen), (vec, Vec&&)) noexcept : data(vec.data()) , dim(vec.rows()) , stride(vec.innerStride()) { } VEG_INLINE auto as_const() const noexcept -> StridedVectorView { return { from_ptr_size_stride, data, dim, stride, }; } VEG_INLINE auto ptr(isize index) const noexcept -> T* { return data + stride * index; } VEG_INLINE auto operator()(isize index) const noexcept -> T& { return *ptr(index); } VEG_INLINE auto segment(isize i, isize size) const noexcept -> StridedVectorViewMut { return { from_ptr_size_stride, data + stride * i, size, stride, }; } VEG_INLINE auto to_eigen() const -> detail::EigenVecMapMut> { return detail::EigenVecMapMut>( data, Eigen::Index(dim), Eigen::Index(1), Eigen::InnerStride(Eigen::Index(stride))); } }; template struct MatrixView { T const* data; isize rows; isize cols; isize outer_stride; VEG_INLINE MatrixView(FromPtrRowsColsStride /*tag*/, T const* _data, isize _rows, isize _cols, isize _outer_stride) noexcept : data(_data) , rows(_rows) , cols(_cols) , outer_stride(_outer_stride) { } VEG_TEMPLATE(typename Mat, requires(LDLT_CONCEPT(eigen_view) && eigen::GetLayout>::value == L), VEG_INLINE MatrixView, (/*tag*/, FromEigen), (mat, Mat const&)) noexcept : data(mat.data()) , rows(mat.rows()) , cols(mat.cols()) , outer_stride(mat.outerStride()) { } VEG_INLINE auto ptr(isize row, isize col) const noexcept -> T const* { return detail::ElementAccess::offset(data, row, col, outer_stride); } VEG_INLINE auto operator()(isize row, isize col) const noexcept -> T const& { return *ptr(row, col); } VEG_INLINE auto block(isize row, isize col, isize nrows, isize ncols) const noexcept -> MatrixView { return { from_ptr_rows_cols_stride, detail::ElementAccess::offset(data, row, col, outer_stride), nrows, ncols, outer_stride, }; } private: VEG_INLINE auto col_impl( proxsuite::linalg::veg::meta::constant /*tag*/, isize c) const noexcept -> VectorView { return { from_ptr_size, data + c * outer_stride, rows, }; } VEG_INLINE auto col_impl( proxsuite::linalg::veg::meta::constant /*tag*/, isize c) const noexcept -> StridedVectorView { return { from_ptr_size_stride, data + c, rows, outer_stride, }; } public: VEG_INLINE auto col(isize c) const noexcept -> proxsuite::linalg::veg::meta:: if_t<(L == colmajor), VectorView, StridedVectorView> { return col_impl(proxsuite::linalg::veg::meta::constant{}, c); } VEG_INLINE auto row(isize r) const noexcept -> proxsuite::linalg::veg::meta:: if_t<(L == rowmajor), VectorView, StridedVectorView> { return trans().col(r); } VEG_INLINE auto trans() const noexcept -> MatrixView { return { from_ptr_rows_cols_stride, data, cols, rows, outer_stride, }; } VEG_INLINE auto to_eigen() const noexcept -> detail::EigenMatMap { return detail::EigenMatMap( data, Eigen::Index(rows), Eigen::Index(cols), Eigen::OuterStride(Eigen::Index(outer_stride))); } }; template struct MatrixViewMut { T* data; isize rows; isize cols; isize outer_stride; VEG_INLINE MatrixViewMut(FromPtrRowsColsStride /*tag*/, T* _data, isize _rows, isize _cols, isize _outer_stride) noexcept : data(_data) , rows(_rows) , cols(_cols) , outer_stride(_outer_stride) { } VEG_TEMPLATE(typename Mat, requires(LDLT_CONCEPT(eigen_view) && eigen::GetLayout>::value == L), VEG_INLINE MatrixViewMut, (/*tag*/, FromEigen), (mat, Mat&&)) noexcept : data(mat.data()) , rows(mat.rows()) , cols(mat.cols()) , outer_stride(mat.outerStride()) { } VEG_INLINE auto ptr(isize row, isize col) const noexcept -> T* { return detail::ElementAccess::offset(data, row, col, outer_stride); } VEG_INLINE auto operator()(isize row, isize col) const noexcept -> T& { return *ptr(row, col); } VEG_INLINE auto block(isize row, isize col, isize nrows, isize ncols) const noexcept -> MatrixViewMut { return { from_ptr_rows_cols_stride, detail::ElementAccess::offset(data, row, col, outer_stride), nrows, ncols, outer_stride, }; } private: VEG_INLINE auto col_impl( proxsuite::linalg::veg::meta::constant /*tag*/, isize c) const noexcept -> VectorViewMut { return { from_ptr_size, data + c * outer_stride, rows, }; } VEG_INLINE auto col_impl( proxsuite::linalg::veg::meta::constant /*tag*/, isize c) const noexcept -> StridedVectorViewMut { return { from_ptr_size_stride, data + c, rows, outer_stride, }; } public: VEG_INLINE auto col(isize c) const noexcept -> proxsuite::linalg::veg::meta:: if_t<(L == colmajor), VectorViewMut, StridedVectorViewMut> { return col_impl(proxsuite::linalg::veg::meta::constant{}, c); } VEG_INLINE auto row(isize r) const noexcept -> proxsuite::linalg::veg::meta:: if_t<(L == rowmajor), VectorViewMut, StridedVectorViewMut> { return trans().col(r); } VEG_INLINE auto trans() const noexcept -> MatrixViewMut { return { from_ptr_rows_cols_stride, data, cols, rows, outer_stride, }; } VEG_INLINE auto to_eigen() const noexcept -> detail::EigenMatMapMut { return detail::EigenMatMapMut( data, Eigen::Index(rows), Eigen::Index(cols), Eigen::OuterStride(Eigen::Index(outer_stride))); } VEG_INLINE auto as_const() const noexcept -> MatrixView { return { from_ptr_rows_cols_stride, data, rows, cols, outer_stride, }; } }; template struct LdltView { private: MatrixView ld; public: explicit LdltView(MatrixView ld) noexcept : ld(ld) { VEG_DEBUG_ASSERT(ld.rows == ld.cols); } VEG_INLINE auto l() const noexcept -> MatrixView { return ld; } VEG_INLINE auto d() const noexcept -> StridedVectorView { return { from_ptr_size_stride, ld.data, ld.rows, ld.outer_stride + 1 }; } VEG_INLINE auto head(isize k) const -> LdltView { return LdltView{ ld.block(0, 0, k, k) }; } VEG_INLINE auto tail(isize k) const -> LdltView { isize n = ld.rows; return LdltView{ ld.block(n - k, n - k, k, k) }; } }; template struct LdltViewMut { private: MatrixViewMut ld; public: explicit LdltViewMut(MatrixViewMut ld) noexcept : ld(ld) { VEG_DEBUG_ASSERT(ld.rows == ld.cols); } VEG_INLINE auto l() const noexcept -> MatrixView { return ld.as_const(); } VEG_INLINE auto l_mut() const noexcept -> MatrixViewMut { return ld; } VEG_INLINE auto d() const noexcept -> StridedVectorView { return { from_ptr_size_stride, ld.data, ld.rows, ld.outer_stride + 1 }; } VEG_INLINE auto d_mut() const noexcept -> StridedVectorViewMut { return { from_ptr_size_stride, ld.data, ld.rows, ld.outer_stride + 1 }; } VEG_INLINE auto as_const() const noexcept -> LdltView { return LdltView{ ld.as_const() }; } VEG_INLINE auto head(isize k) const -> LdltViewMut { return LdltViewMut{ ld.block(0, 0, k, k) }; } VEG_INLINE auto tail(isize k) const -> LdltViewMut { isize n = ld.rows; return LdltViewMut{ ld.block(n - k, n - k, k, k) }; } }; namespace detail { template void noalias_mul_add(MatrixViewMut dst, MatrixView lhs, MatrixView rhs, T factor) { if ((dst.cols == 0) || (dst.rows == 0) || (lhs.cols == 0)) { return; } #if !EIGEN_VERSION_AT_LEAST(3, 3, 8) #define LAZY_PRODUCT(a, b) a.lazyProduct(b) #else #define LAZY_PRODUCT(a, b) a.operator*(b) #endif if (dst.cols == 1 && dst.rows == 1) { // dot auto rhs_col = rhs.col(0); auto lhs_row = lhs.row(0); auto lhs_as_col = lhs.col(0); lhs_as_col.dim = lhs_row.dim; if (lhs_row.stride == 1) { dst(0, 0) += factor * lhs_as_col.to_eigen().dot(rhs_col.to_eigen()); } else { dst(0, 0) += factor * lhs_row.to_eigen().dot(rhs_col.to_eigen()); } } else if (dst.cols == 1) { // gemv auto rhs_col = rhs.col(0); auto dst_col = dst.col(0); dst_col.to_eigen().noalias().operator+=( factor * LAZY_PRODUCT(lhs.to_eigen(), rhs_col.to_eigen())); } #if !EIGEN_VERSION_AT_LEAST(3, 3, 8) else if ((dst.rows < 20) && (dst.cols < 20) && (rhs.rows < 20)) { // gemm // workaround for eigen 3.3.7 bug: // https://gitlab.com/libeigen/eigen/-/issues/1562 using Stride = Eigen::OuterStride; using Mat = Eigen::Matrix; using MapMut = Eigen::Map; using Map = Eigen::Map; MapMut(dst.data, dst.rows, dst.cols, Stride(dst.outer_stride)) .noalias() . operator+=( factor * LAZY_PRODUCT( Map(lhs.data, lhs.rows, lhs.cols, Stride(lhs.outer_stride)), Map(rhs.data, rhs.rows, rhs.cols, Stride(rhs.outer_stride)))); } #endif else { // gemm dst.to_eigen().noalias().operator+=( factor * LAZY_PRODUCT(lhs.to_eigen(), rhs.to_eigen())); } #undef LAZY_PRODUCT } template void noalias_mul_add_vec(VectorViewMut dst, MatrixView lhs, VectorView rhs, T factor) { detail::noalias_mul_add( { from_ptr_rows_cols_stride, dst.data, dst.dim, 1, 0, }, lhs, { from_ptr_rows_cols_stride, rhs.data, rhs.dim, 1, 0, }, VEG_FWD(factor)); } template auto dot(StridedVectorView lhs, VectorView rhs) -> T { auto out = T(0); detail::noalias_mul_add( { from_ptr_rows_cols_stride, std::addressof(out), 1, 1, 0, }, { from_ptr_rows_cols_stride, lhs.data, 1, lhs.dim, lhs.stride, }, { from_ptr_rows_cols_stride, rhs.data, rhs.dim, 1, 0, }, 1); return out; } template void assign_cwise_prod(VectorViewMut out, StridedVectorView lhs, StridedVectorView rhs) { out.to_eigen() = lhs.to_eigen().cwiseProduct(rhs.to_eigen()); } template void assign_scalar_prod(VectorViewMut out, T factor, VectorView in) { out.to_eigen() = in.to_eigen().operator*(factor); } template void trans_tr_unit_up_solve_in_place_on_right(MatrixView tr, MatrixViewMut rhs) { if (rhs.cols == 1) { tr.to_eigen() .transpose() .template triangularView() .template solveInPlace(rhs.col(0).to_eigen()); } else { tr.to_eigen() .transpose() .template triangularView() .template solveInPlace(rhs.to_eigen()); } } template void apply_diag_inv_on_right(MatrixViewMut out, StridedVectorView d, MatrixView in) { if (out.cols == 1) { out.col(0).to_eigen() = in.col(0).to_eigen().operator*(d.to_eigen().asDiagonal().inverse()); } else { out.to_eigen() = in.to_eigen().operator*(d.to_eigen().asDiagonal().inverse()); } } template void apply_diag_on_right(MatrixViewMut out, StridedVectorView d, MatrixView in) { if (out.cols == 1) { out.col(0).to_eigen() = in.col(0).to_eigen().operator*(d.to_eigen().asDiagonal()); } else { out.to_eigen() = in.to_eigen().operator*(d.to_eigen().asDiagonal()); } } template void noalias_mul_sub_tr_lo(MatrixViewMut out, MatrixView lhs, MatrixView rhs) { if (lhs.cols == 1) { out.to_eigen().template triangularView().operator-=( lhs.col(0).to_eigen().operator*( Eigen::Map const>( rhs.data, 1, rhs.cols))); } else { out.to_eigen().template triangularView().operator-=( lhs.to_eigen().operator*(rhs.to_eigen())); } } } // namespace detail } // namespace proxqp } // namespace proxsuite namespace proxsuite { namespace proxqp { namespace dense { struct EigenAllowAlloc { bool alloc_was_allowed; EigenAllowAlloc(EigenAllowAlloc&&) = delete; EigenAllowAlloc(EigenAllowAlloc const&) = delete; auto operator=(EigenAllowAlloc&&) -> EigenAllowAlloc& = delete; auto operator=(EigenAllowAlloc const&) -> EigenAllowAlloc& = delete; #if defined(EIGEN_RUNTIME_NO_MALLOC) EigenAllowAlloc() noexcept : alloc_was_allowed(Eigen::internal::is_malloc_allowed()) { Eigen::internal::set_is_malloc_allowed(true); } ~EigenAllowAlloc() noexcept { Eigen::internal::set_is_malloc_allowed(alloc_was_allowed); } #else EigenAllowAlloc() = default; #endif }; template struct QpView { static constexpr Layout layout = rowmajor; MatrixView H; VectorView g; MatrixView A; VectorView b; MatrixView C; VectorView d; }; template struct QpViewBox { static constexpr Layout layout = rowmajor; MatrixView H; VectorView g; MatrixView A; VectorView b; MatrixView C; VectorView u; VectorView l; }; template struct QpViewMut { static constexpr Layout layout = rowmajor; MatrixViewMut H; VectorViewMut g; MatrixViewMut A; VectorViewMut b; MatrixViewMut C; VectorViewMut d; VEG_INLINE constexpr auto as_const() const noexcept -> QpView { return { H.as_const(), g.as_const(), A.as_const(), b.as_const(), C.as_const(), d.as_const(), }; } }; template struct QpViewBoxMut { static constexpr Layout layout = rowmajor; MatrixViewMut H; VectorViewMut g; MatrixViewMut A; VectorViewMut b; MatrixViewMut C; VectorViewMut u; VectorViewMut l; VEG_INLINE constexpr auto as_const() const noexcept -> QpViewBox { return { H.as_const(), g.as_const(), A.as_const(), b.as_const(), C.as_const(), u.as_const(), l.as_const(), }; } }; namespace nb { struct pow { template auto operator()(T x, T y) const -> T { using std::pow; return pow(x, y); } }; struct infty_norm { template auto operator()(Eigen::MatrixBase const& mat) const -> typename D::Scalar { if (mat.rows() == 0 || mat.cols() == 0) { return typename D::Scalar(0); } else { return mat.template lpNorm(); } } }; struct sqrt { template auto operator()(T x) const -> T { using std::sqrt; return sqrt(x); } }; struct fabs { template auto operator()(T x) const -> T { using std::fabs; return fabs(x); } }; } // namespace nb VEG_NIEBLOID(fabs); VEG_NIEBLOID(sqrt); VEG_NIEBLOID(pow); VEG_NIEBLOID(infty_norm); } // namespace dense } // namespace proxqp } // namespace proxsuite #endif /* end of include guard PROXSUITE_PROXQP_DENSE_VIEWS_HPP */