eigen_util.h Source File

CPP API: eigen_util.h Source File
eigen_util.h
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2020-2026 MEmilio
3 *
4 * Authors: Daniel Abele
5 *
6 * Contact: Martin J. Kuehn <Martin.Kuehn@DLR.de>
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20 #ifndef MIO_MATH_EIGEN_UTIL_H
21 #define MIO_MATH_EIGEN_UTIL_H
22 
23 #include "memilio/math/eigen.h" // IWYU pragma: keep
24 
25 #include <utility>
26 #include <iterator>
27 
28 namespace mio
29 {
30 
34 template <typename T>
35 struct Seq {
36  Seq(T start_, T n_, T stride_ = 1)
37  : start(start_)
38  , n(n_)
39  , stride(stride_)
40  {
41  assert(start >= 0);
42  assert(n >= 0);
43  assert(stride >= 1);
44  }
45  T start, n, stride = 1;
46 };
47 
51 template <class M>
52 concept IsDynamicVector = (std::remove_reference_t<M>::RowsAtCompileTime == Eigen::Dynamic &&
53  std::remove_reference_t<M>::ColsAtCompileTime == 1) ||
54  (std::remove_reference_t<M>::RowsAtCompileTime == 1 &&
55  std::remove_reference_t<M>::ColsAtCompileTime == Eigen::Dynamic);
56 
60 template <class M>
61 concept IsDynamicMatrix = std::remove_reference_t<M>::RowsAtCompileTime == Eigen::Dynamic &&
62  std::remove_reference_t<M>::ColsAtCompileTime == Eigen::Dynamic;
63 
67 template <class M>
68 Eigen::Index major_size(M&& m)
69 {
70  return std::remove_reference_t<M>::IsRowMajor ? m.rows() : m.cols();
71 }
72 
76 template <class M>
77 Eigen::Index minor_size(M&& m)
78 {
79  return std::remove_reference_t<M>::IsRowMajor ? m.cols() : m.rows();
80 }
81 
86 template <class M>
87 struct CVPlainMatrix {
88  using Type = typename M::PlainMatrix;
89 };
90 template <class M>
91 struct CVPlainMatrix<Eigen::Ref<const M>> {
92  using Type = const M;
93 };
94 template <class M>
96 
106 template <IsDynamicVector V>
107 auto slice(V&& v, Seq<Eigen::Index> elems)
108 {
109  return Eigen::Map<CVPlainMatrixT<std::decay_t<V>>, 0, Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>>(
110  v.data() + elems.start, elems.n, Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>{1, elems.stride});
111 }
112 
123 template <IsDynamicMatrix M>
125 {
126  assert(rows.start + rows.stride * rows.n <= m.rows());
127  assert(cols.start + cols.stride * cols.n <= m.cols());
128 
129  auto majSpec = std::remove_reference_t<M>::IsRowMajor ? rows : cols;
130  auto minSpec = std::remove_reference_t<M>::IsRowMajor ? cols : rows;
131  auto majStride = majSpec.stride * minor_size(m);
132  auto minStride = minSpec.stride;
133  auto data = m.data() + majSpec.start * minor_size(m) + minSpec.start;
134 
135  return Eigen::Map<CVPlainMatrixT<std::remove_reference_t<M>>, Eigen::Unaligned,
136  Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>>(data, rows.n, cols.n, {majStride, minStride});
137 }
138 
150 template <typename M>
151 auto reshape(M&& m, Eigen::Index rows, Eigen::Index cols)
152 {
153  assert(rows * cols == m.rows() * m.cols());
154  assert(rows >= 1);
155  assert(cols >= 1);
156 
157  return Eigen::Map<CVPlainMatrixT<std::remove_reference_t<M>>>(m.data(), rows, cols);
158 }
159 
161 template <class M>
162 concept IsMatrixExpression = std::is_base_of_v<Eigen::EigenBase<M>, M>;
163 
170 template <class A, class B>
171 auto max(const Eigen::MatrixBase<A>& a, B&& b)
172 {
173  using std::max;
174  return a.binaryExpr(std::forward<B>(b), [](auto a_i, auto b_i) {
175  return max(a_i, b_i);
176  });
177 }
178 
188 template <class Rng, class F>
189 auto map(const Rng& v, F f)
190 {
191  using Result = std::invoke_result_t<F, const typename Rng::value_type&>;
192  using Scalar = std::decay_t<Result>;
193  using Array = Eigen::Array<Scalar, Eigen::Dynamic, 1>;
194  return Array::NullaryExpr(v.size(), [f, &v](Eigen::Index i) -> Scalar {
195  return f(v[size_t(i)]);
196  });
197 }
198 
199 namespace details
200 {
201 //true if elements returned by matrix(i, j) are references where matrix is of type M;
202 //false if the elements are temporaries, e.g. for expressions like Eigen::MatrixXd::Constant(r, c, v).
203 template <class M>
205  std::is_reference_v<decltype(std::declval<M>()(std::declval<Eigen::Index>(), std::declval<Eigen::Index>()))>;
206 } // namespace details
207 
213 template <class M, bool IsConst = false>
215 {
216 public:
217  using MatrixRef = std::conditional_t<IsConst, const M&, M&>;
218  using MatrixPtr = std::conditional_t<IsConst, const M*, M*>;
219  static_assert(IsConst || details::IsElementReference<M>, "Iterator must be const if matrix is not in memory.");
220 
221  using iterator_category = std::random_access_iterator_tag;
222  using value_type = typename M::Scalar;
223  using reference = std::conditional_t<IsConst, const value_type&, value_type&>;
224  using difference_type = Eigen::Index;
225 
226  // Operator-> returns a pointer to an element if the element can be referenced.
227  // If the matrix returns temporaries, a proxy is returned that holds a local copy
228  // and forwards the address of that copy. Adress is pointer-to-const because modifying
229  // the local inside the proxy is almost certainly not what is intended.
230  struct Proxy {
232  const value_type* operator->() const
233  {
234  return &value;
235  }
236  };
237  using pointer = std::conditional_t<details::IsElementReference<MatrixRef>,
238  std::conditional_t<IsConst, const value_type*, value_type*>, Proxy>;
239 
246  RowMajorIterator(MatrixRef m, Eigen::Index i)
247  : m_matrix(&m)
248  , m_i(i)
249  {
250  }
251 
252  explicit RowMajorIterator()
253  : m_matrix(nullptr)
254  , m_i(0)
255  {
256  }
257 
262  {
263  ++m_i;
264  return *this;
265  }
270  {
271  auto cpy = *this;
272  ++m_i;
273  return cpy;
274  }
279  {
280  return {*m_matrix, m_i + n};
281  }
286  {
287  return {*iter.m_matrix, iter.m_i + n};
288  }
293  {
294  m_i += n;
295  return *this;
296  }
301  {
302  --m_i;
303  return *this;
304  }
309  {
310  auto cpy = *this;
311  --m_i;
312  return cpy;
313  }
318  {
319  return {*m_matrix, m_i - n};
320  }
325  {
326  m_i -= n;
327  return *this;
328  }
333  {
334  return m_i - r.m_i;
335  }
336 
342  decltype(auto) operator*() const
343  {
344  return (*m_matrix)(m_i / m_matrix->cols(), m_i % m_matrix->cols());
345  }
346 
356  {
357  return &(**this);
358  }
359 
360  pointer operator->() const
362  {
363  return Proxy{**this};
364  }
370  bool operator<(const RowMajorIterator& other) const
371  {
372  return m_i < other.m_i;
373  }
377  bool operator>(const RowMajorIterator& other) const
378  {
379  return other < *this;
380  }
384  bool operator<=(const RowMajorIterator& other) const
385  {
386  return !(other < *this);
387  }
391  bool operator>=(const RowMajorIterator& other) const
392  {
393  return !(*this < other);
394  }
398  bool operator==(const RowMajorIterator& other) const
399  {
400  return !(*this < other) && !(other < *this);
401  }
405  bool operator!=(const RowMajorIterator& other) const
406  {
407  return !(*this == other);
408  }
409 
410 private:
412  Eigen::Index m_i;
413 };
414 
419 template <IsMatrixExpression M>
420  requires details::IsElementReference<M>
422 {
423  return {m, 0};
424 }
425 
429 template <IsMatrixExpression M>
431 {
432  return {m, 0};
433 }
434 
438 template <IsMatrixExpression M>
440 {
441  return {m, 0};
442 }
443 
447 template <IsMatrixExpression M>
448  requires details::IsElementReference<M>
450 {
451  return {m, m.size()};
452 }
453 
457 template <IsMatrixExpression M>
459 {
460  return {m, m.size()};
461 }
462 
466 template <IsMatrixExpression M>
468 {
469  return {m, m.size()};
470 }
471 
472 } // namespace mio
473 
474 #endif // MIO_MATH_EIGEN_UTIL_H
iterate over elements of eigen matrix expressions in row major order.
Definition: eigen_util.h:215
typename M::Scalar value_type
Definition: eigen_util.h:222
std::conditional_t< IsConst, const M &, M & > MatrixRef
Definition: eigen_util.h:217
RowMajorIterator(MatrixRef m, Eigen::Index i)
Create an iterator that points to a specific element.
Definition: eigen_util.h:246
RowMajorIterator & operator+=(difference_type n)
add n to index of this.
Definition: eigen_util.h:292
std::conditional_t< IsConst, const value_type &, value_type & > reference
Definition: eigen_util.h:223
bool operator<=(const RowMajorIterator &other) const
lesser equal comparison operator.
Definition: eigen_util.h:384
std::conditional_t< details::IsElementReference< MatrixRef >, std::conditional_t< IsConst, const value_type *, value_type * >, Proxy > pointer
Definition: eigen_util.h:238
MatrixPtr m_matrix
Definition: eigen_util.h:411
bool operator<(const RowMajorIterator &other) const
lesser comparison operator.
Definition: eigen_util.h:370
RowMajorIterator operator++(int)
post increment operator.
Definition: eigen_util.h:269
difference_type operator-(RowMajorIterator r) const
calculate the distance between this and r.
Definition: eigen_util.h:332
Eigen::Index m_i
Definition: eigen_util.h:412
RowMajorIterator operator-(difference_type n) const
take n from the index of this.
Definition: eigen_util.h:317
RowMajorIterator operator--(int)
post decrement operator.
Definition: eigen_util.h:308
Eigen::Index difference_type
Definition: eigen_util.h:224
RowMajorIterator operator+(difference_type n) const
random access, add n to index of this.
Definition: eigen_util.h:278
RowMajorIterator & operator-=(difference_type n)
take n from the index of this.
Definition: eigen_util.h:324
std::random_access_iterator_tag iterator_category
Definition: eigen_util.h:221
friend RowMajorIterator operator+(difference_type n, const RowMajorIterator &iter)
random access, add n to index of iterator.
Definition: eigen_util.h:285
RowMajorIterator()
Definition: eigen_util.h:252
RowMajorIterator & operator++()
pre increment operator.
Definition: eigen_util.h:261
bool operator>=(const RowMajorIterator &other) const
greater equal comparison operator.
Definition: eigen_util.h:391
RowMajorIterator & operator--()
pre decrement operator.
Definition: eigen_util.h:300
bool operator>(const RowMajorIterator &other) const
greater than comparison operator.
Definition: eigen_util.h:377
bool operator==(const RowMajorIterator &other) const
equality comparison operator.
Definition: eigen_util.h:398
std::conditional_t< IsConst, const M *, M * > MatrixPtr
Definition: eigen_util.h:218
bool operator!=(const RowMajorIterator &other) const
inequality comparison operator.
Definition: eigen_util.h:405
pointer operator->() const requires details
get a pointer to the element this iterator points to.
Definition: eigen_util.h:354
Definition: ad.h:57
concept IsElementReference
Definition: eigen_util.h:204
A collection of classes to simplify handling of matrix shapes in meta programming.
Definition: models/abm/analyze_result.h:30
requires details::IsElementReference< M > RowMajorIterator< M, false > end(M &m)
create a non-const end iterator for the matrix m.
Definition: eigen_util.h:449
auto reshape(M &&m, Eigen::Index rows, Eigen::Index cols)
reshape the matrix.
Definition: eigen_util.h:151
Eigen::Index minor_size(M &&m)
number of columns (rows) of a row (column) major matrix.
Definition: eigen_util.h:77
auto i
Definition: io.h:809
RowMajorIterator< M, true > cend(const M &m)
create a non-const end iterator for the matrix m.
Definition: eigen_util.h:467
Eigen::Index major_size(M &&m)
number of rows (columns) of a row (column) major matrix.
Definition: eigen_util.h:68
requires(!std::is_trivial_v< T >) void BinarySerializerObject
Definition: binary_serializer.h:333
auto map(const Rng &v, F f)
Maps a random access range (i.e.
Definition: eigen_util.h:189
concept IsMatrixExpression
Concept to detect whether T is an Eigen matrix expression.
Definition: eigen_util.h:162
auto slice(V &&v, Seq< Eigen::Index > elems)
take a regular slice of a row or column vector.
Definition: eigen_util.h:107
auto max(const Eigen::MatrixBase< A > &a, B &&b)
coefficient wise maximum of two matrices.
Definition: eigen_util.h:171
requires details::IsElementReference< M > RowMajorIterator< M, false > begin(M &m)
create a non-const iterator to first element of the matrix m.
Definition: eigen_util.h:421
RowMajorIterator< M, true > cbegin(const M &m)
create a const iterator to first element of the matrix m.
Definition: eigen_util.h:439
concept IsDynamicVector
check if Eigen::Matrix type M is a dynamic vector type.
Definition: eigen_util.h:52
concept IsDynamicMatrix
check if Eigen::Matrix type M is a dynamic matrix type.
Definition: eigen_util.h:61
typename CVPlainMatrix< M >::Type CVPlainMatrixT
Definition: eigen_util.h:95
const M Type
Definition: eigen_util.h:92
helper to get the matrix type from an eigen expression with correct const volatile qualitfications.
Definition: eigen_util.h:87
typename M::PlainMatrix Type
Definition: eigen_util.h:88
Definition: eigen_util.h:230
value_type value
Definition: eigen_util.h:231
const value_type * operator->() const
Definition: eigen_util.h:232
sequence of indices
Definition: eigen_util.h:35
T start
Definition: eigen_util.h:45
Seq(T start_, T n_, T stride_=1)
Definition: eigen_util.h:36
T stride
Definition: eigen_util.h:45
T n
Definition: eigen_util.h:45