guanaqo 1.0.0-alpha.26
Utilities for scientific software
Loading...
Searching...
No Matches
view.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file
4/// @ingroup linalg_views
5/// Conversions between Eigen expressions, maps and refs, and guanaqo::MatrixView.
6
8
9#include <Eigen/Core>
10#include <type_traits>
11
12namespace guanaqo {
13
14template <class I>
16template <class I>
18
19namespace detail {
20
21template <class Derived, class I>
22auto as_view_impl(auto &M) {
23 auto *const data = M.derived().data();
24 using T = std::remove_pointer_t<decltype(data)>;
25 using Scalar = typename Derived::Scalar;
26 static_assert(std::is_same_v<Scalar, std::remove_const_t<T>>);
27 static constexpr auto O =
28 Derived::IsRowMajor ? StorageOrder::RowMajor : StorageOrder::ColMajor;
29 const auto rows = static_cast<I>(M.derived().rows()),
30 cols = static_cast<I>(M.derived().cols()),
31 outer_stride = static_cast<I>(M.derived().outerStride());
32 constexpr auto static_inner_stride = Derived::InnerStrideAtCompileTime;
33 // Dynamic (run-time) inner stride
34 if constexpr (static_inner_stride == Eigen::Dynamic) {
35 const auto inner_stride = static_cast<I>(M.derived().innerStride());
36 return MatrixView<T, I, I, O>{{.data = data,
37 .rows = rows,
38 .cols = cols,
39 .inner_stride = inner_stride,
40 .outer_stride = outer_stride}};
41 }
42 // Compile-time inner stride
43 else {
44 using S = std::integral_constant<I, static_inner_stride>;
45 return MatrixView<T, I, S, O>{{.data = data,
46 .rows = rows,
47 .cols = cols,
48 .outer_stride = outer_stride}};
49 }
50}
51
52} // namespace detail
53
54/// @addtogroup linalg_views
55/// @{
56
57// Conversions from Eigen expressions to MatrixView
58
59// We need overloads for const and non-const references because some Eigen types
60// have deep constness (i.e. if the matrix itself is const, the .data() function
61// returns a pointer to const).
62// Then we also need overloads for rvalues because we want to prevent dangling
63// pointers to temporaries. We need the const rvalue reference overload because
64// Eigen's .eval() member function returns a const Eigen::Matrix, so it does not
65// match the normal rvalue reference overload.
66
67/// Convert an Eigen matrix view to a guanaqo::MatrixView.
68template <class Derived, class I = typename Derived::Index>
69auto as_view(Eigen::DenseBase<Derived> &M, with_index_type_t<I> = {}) {
71}
72
73/// Convert an Eigen matrix view to a guanaqo::MatrixView.
74template <class Derived, class I = typename Derived::Index>
75auto as_view(const Eigen::DenseBase<Derived> &M, with_index_type_t<I> = {}) {
77}
78
79/// Convert an Eigen matrix view to a guanaqo::MatrixView.
80template <class Derived, class I = typename Derived::Index>
81auto as_view(Eigen::DenseBase<Derived> &&M, with_index_type_t<I> = {}) {
83}
84
85/// Convert an Eigen matrix view to a guanaqo::MatrixView.
86template <class Derived, class I = typename Derived::Index>
87auto as_view(const Eigen::DenseBase<Derived> &&M, with_index_type_t<I> = {}) {
89}
90
91template <class Derived, class I = typename Derived::Index>
92 requires(std::is_base_of_v<Eigen::PlainObjectBase<std::decay_t<Derived>>,
93 std::decay_t<Derived>>)
94auto as_view( // Refusing to return a view to a temporary Eigen matrix with its own storage
95 Eigen::DenseBase<Derived> &&M, with_index_type_t<I> = {}) = delete;
96
97template <class Derived, class I = typename Derived::Index>
98 requires(std::is_base_of_v<Eigen::PlainObjectBase<std::decay_t<Derived>>,
99 std::decay_t<Derived>>)
100auto as_view( // Refusing to return a view to a temporary Eigen matrix with its own storage
101 const Eigen::DenseBase<Derived> &&M, with_index_type_t<I> = {}) = delete;
102
103// Conversions from MatrixView to Eigen::Map
104
105/// Convert a guanaqo::MatrixView to an Eigen::Matrix view.
106template <class T, class I, class S, StorageOrder O>
108 constexpr auto Opt = M.is_row_major ? Eigen::RowMajor : Eigen::ColMajor;
109 constexpr auto X = Eigen::Dynamic;
110 using Scalar = std::remove_const_t<T>;
111 using Mat = Eigen::Matrix<Scalar, X, X, Opt>;
112 using CMat = std::conditional_t<std::is_const_v<T>, const Mat, Mat>;
113 using Index = typename Mat::Index;
114 const auto rows = static_cast<Index>(M.rows),
115 cols = static_cast<Index>(M.cols),
116 outer_stride = static_cast<Index>(M.outer_stride);
117 // Case where inner stride is a compile-time constant
118 if constexpr (requires { S::value; }) {
119 static constexpr auto inner_stride = static_cast<Index>(M.inner_stride);
120 // Eigen does not support zero stride at compile time (it is interpreted
121 // as unit stride). The value -1 is reserved as well, so it cannot be
122 // used as a compile-time stride either. We therefore use a dynamic
123 // stride, and set the run-time value to 0 or -1.
124 if constexpr (inner_stride == 0 || inner_stride == Eigen::Dynamic) {
125 using Stride = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>;
126 using Map = Eigen::Map<CMat, 0, Stride>;
127 return Map{M.data, rows, cols, {outer_stride, inner_stride}};
128 }
129 // Unit inner stride
130 else if constexpr (inner_stride == 1) {
131 using Stride = Eigen::OuterStride<>;
132 using Map = Eigen::Map<CMat, 0, Stride>;
133 return Map{M.data, rows, cols, {outer_stride}};
134 }
135 // Fixed inner stride >1
136 else {
137 using Stride = Eigen::Stride<Eigen::Dynamic, inner_stride>;
138 using Map = Eigen::Map<CMat, 0, Stride>;
139 return Map{M.data, rows, cols, {outer_stride, inner_stride}};
140 }
141 }
142 // Both inner and outer stride are dynamic
143 else {
144 const auto inner_stride = static_cast<Index>(M.inner_stride);
145 using Stride = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>;
146 using Map = Eigen::Map<CMat, 0, Stride>;
147 return Map{M.data, rows, cols, {outer_stride, inner_stride}};
148 }
149}
150
151/// @}
152
153} // namespace guanaqo
auto as_view(Eigen::DenseBase< Derived > &M, with_index_type_t< I >={})
Convert an Eigen matrix view to a guanaqo::MatrixView.
Definition view.hpp:69
auto as_eigen(std::span< T, E > s)
Convert a std::span to an Eigen::Vector view.
Definition span.hpp:62
@ ColMajor
Column-major storage order (Fortran-style, layout left, unit row stride).
Definition mat-view.hpp:22
@ RowMajor
Row-major storage order (C-style, layout right, unit column stride).
Definition mat-view.hpp:24
Non-owning matrix view.
auto as_view_impl(auto &M)
Definition view.hpp:22
constexpr with_index_type_t< I > with_index_type
Definition view.hpp:17
A lightweight view of a 2D matrix.
Definition mat-view.hpp:68
index_type outer_stride
Definition mat-view.hpp:80
inner_stride_type inner_stride
Definition mat-view.hpp:79
static constexpr bool is_row_major
Definition mat-view.hpp:74
value_type * data
Definition mat-view.hpp:76