OpenKalman
indexible_object_traits_base.hpp
Go to the documentation of this file.
1 /* This file is part of OpenKalman, a header-only C++ library for
2  * Kalman filters and other recursive filters.
3  *
4  * Copyright (c) 2019-2023 Christopher Lee Ogden <ogden@gatech.edu>
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
9  */
10 
16 #ifndef OPENKALMAN_INDEXIBLE_OBJECT_TRAITS_BASE_HPP
17 #define OPENKALMAN_INDEXIBLE_OBJECT_TRAITS_BASE_HPP
18 
19 #include <type_traits>
20 #include <tuple>
21 
22 
23 namespace OpenKalman::Eigen3
24 {
25 #ifdef __cpp_concepts
26  template<Eigen3::eigen_general T>
27  struct indexible_object_traits_base<T>
28 #else
29  template<typename T>
30  struct indexible_object_traits_base<T, std::enable_if_t<Eigen3::eigen_general<T>>>
31 #endif
32  {
33  private:
34 
35  using IndexType = typename T::Index; // static_assert(values::index<IndexType>);
36 
37  public:
38 
39  using scalar_type = typename T::Scalar;
40 
41 
42  template<typename Arg>
43  static constexpr auto
44  count_indices(const Arg& arg)
45  {
46  constexpr bool lin = (Eigen::internal::evaluator<Arg>::Flags & Eigen::LinearAccessBit) != 0x0;
47  if constexpr (Arg::RowsAtCompileTime == 1 and Arg::ColsAtCompileTime == 1)
48  return std::integral_constant<std::size_t, 0_uz>{};
49  else if constexpr (Arg::ColsAtCompileTime == 1 and lin)
50  return std::integral_constant<std::size_t, 1_uz>{};
51  else
52  return std::integral_constant<std::size_t, 2_uz>{};
53  }
54 
55 
56  template<typename Arg, typename N>
57  static constexpr auto
58  get_vector_space_descriptor(const Arg& arg, N n)
59  {
60  if constexpr (values::fixed<N>)
61  {
62  constexpr auto dim = n == 0_uz ? Arg::RowsAtCompileTime : Arg::ColsAtCompileTime;
63 
64  if constexpr (dim == Eigen::Dynamic)
65  {
66  if constexpr (n == 0_uz) return static_cast<std::size_t>(arg.rows());
67  else return static_cast<std::size_t>(arg.cols());
68  }
69  else return Dimensions<static_cast<std::size_t>(dim)>{};
70  }
71  else
72  {
73  if (n == 0_uz) return static_cast<std::size_t>(arg.rows());
74  else return static_cast<std::size_t>(arg.cols()); // n == 1_uz
75  // n >= 2 is precluded by the general get_vector_space_descriptor function
76  }
77  }
78 
79  protected:
80 
81  static constexpr bool row_major = (Eigen::internal::traits<T>::Flags & Eigen::RowMajorBit) != 0x0;
82 
83  static constexpr bool direct_access = (Eigen::internal::traits<T>::Flags & Eigen::DirectAccessBit) != 0x0;
84 
85  static constexpr bool lvalue_access = (Eigen::internal::traits<T>::Flags & Eigen::LvalueBit) != 0x0;
86 
87 
88  public:
89 
90  static constexpr bool is_writable = lvalue_access and direct_access;
91 
92 
93 #ifdef __cpp_lib_concepts
94  template<typename Arg> requires requires(Arg&& arg) { {*std::forward<Arg>(arg).data()} -> values::scalar; } and direct_access
95 #else
96  template<typename Arg, std::enable_if_t<values::scalar<decltype(*std::declval<Arg&&>().data())> and direct_access, int> = 0>
97 #endif
98  static constexpr decltype(auto)
99  raw_data(Arg&& arg) { return std::forward<Arg>(arg).data(); }
100 
101  private:
102 
103 #ifdef __cpp_lib_concepts
104  template<typename U>
105 #else
106  template<typename U, typename = void>
107 #endif
108  struct has_strides : std::false_type {};
109 
110 
111 #ifdef __cpp_lib_concepts
112  template<typename U> requires requires(U u) { {u.innerStride()} -> values::index; {u.outerStride()} -> values::index; }
113  struct has_strides<U>
114 #else
115  template<typename U>
116  struct has_strides<U, std::enable_if_t<values::index<decltype(std::declval<U>().innerStride())> and
117  values::index<decltype(std::declval<U>().outerStride())>>>
118 #endif
119  : std::true_type {};
120 
121  public:
122 
123  static constexpr Layout layout = has_strides<T>::value and direct_access ? Layout::stride : row_major ? Layout::right : Layout::left;
124 
125 
126 #ifdef __cpp_lib_concepts
127  template<Eigen3::eigen_dense_general Arg> requires has_strides<T>::value
128 #else
129  template<typename Arg, std::enable_if_t<Eigen3::eigen_dense_general<Arg> and has_strides<T>::value, int> = 0>
130 #endif
131  static auto
132  strides(Arg&& arg)
133  {
134  constexpr auto outer = Eigen::internal::traits<T>::OuterStrideAtCompileTime;
135  constexpr auto inner = Eigen::internal::traits<T>::InnerStrideAtCompileTime;
136  if constexpr (outer != Eigen::Dynamic and inner != Eigen::Dynamic)
137  return std::tuple {std::integral_constant<std::ptrdiff_t, outer>{}, std::integral_constant<std::ptrdiff_t, inner>{}};
138  else if constexpr (outer != Eigen::Dynamic and inner == Eigen::Dynamic)
139  return std::tuple {std::integral_constant<std::ptrdiff_t, outer>{}, arg.innerStride()};
140  else if constexpr (outer == Eigen::Dynamic and inner != Eigen::Dynamic)
141  return std::tuple {arg.outerStride(), std::integral_constant<std::ptrdiff_t, inner>{}};
142  else
143  return std::tuple {arg.outerStride(), arg.innerStride()};
144  }
145 
146  };
147 
148 
149 } // namespace OpenKalman::Eigen3
150 
151 
152 #endif //OPENKALMAN_INDEXIBLE_OBJECT_TRAITS_BASE_HPP
constexpr auto count_indices(const T &t)
Get the number of indices available to address the components of an indexible object.
Definition: count_indices.hpp:33
Row-major storage (C or C++ style): contiguous storage in which the right-most index has a stride of ...
Trait object providing get and set routines.
Definition: eigen-forward-declarations.hpp:502
Definition: tuple_reverse.hpp:103
constexpr bool value
T is numerical value or is reducible to a numerical value.
Definition: value.hpp:31
Column-major storage (Fortran, Matlab, or Eigen style): contiguous storage in which the left-most ext...
Definition: eigen-forward-declarations.hpp:22
A generalization of the above: a custom stride is specified for each index.
Layout
The layout format of a multidimensional array.
Definition: global-definitions.hpp:47
constexpr bool index
T is an index value.
Definition: index.hpp:56
constexpr auto get_vector_space_descriptor(const T &t, const N &n)
Get the coordinates::pattern object for index N of indexible object T.
Definition: get_vector_space_descriptor.hpp:56