OpenKalman
to_diagonal_mdspan_policies.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) 2025-2026 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 
17 #ifndef OPENKALMAN_TO_DIAGONAL_MDSPAN_POLICIES_HPP
18 #define OPENKALMAN_TO_DIAGONAL_MDSPAN_POLICIES_HPP
19 
20 #include "patterns/patterns.hpp"
21 
22 namespace OpenKalman::interface
23 {
28  template<typename NestedLayout, typename NestedExtents>
30  {
31  template<class Extents>
32  struct mapping
33  {
34  using extents_type = Extents;
35  using index_type = typename extents_type::index_type;
36  using size_type = typename extents_type::size_type;
37  using rank_type = typename extents_type::rank_type;
39 
40  private:
41 
42  using nested_extents_type = NestedExtents;
43  using nested_mapping_type = typename NestedLayout:: template mapping<nested_extents_type>;
44 
45  template<typename...Is>
46  constexpr index_type
47  access_with_padded_indices(Is...is) const
48  {
49  if constexpr (sizeof...(Is) < nested_extents_type::rank())
50  return access_with_padded_indices(is..., 0_uz);
51  else
52  return nested_mapping_(is...);
53  }
54 
55  public:
56 
57  constexpr explicit
58  mapping(const nested_mapping_type& map, const extents_type& e)
59  : nested_mapping_(map), extents_(e) {}
60 
61  constexpr const extents_type&
62  extents() const noexcept { return extents_; }
63 
64 #ifdef __cpp_concepts
65  constexpr index_type
66  operator() () const requires (extents_type::rank() == 0)
67 #else
68  template<bool Enable = true, std::enable_if_t<Enable and (extents_type::rank() == 0), int> = 0>
69  constexpr index_type
70  operator() () const
71 #endif
72  {
73  return access_with_padded_indices();
74  }
75 
76 #ifdef __cpp_concepts
77  constexpr index_type
78  operator() (std::convertible_to<index_type> auto i0) const requires (extents_type::rank() == 1)
79 #else
80  template<typename IndexType0, std::enable_if_t<
81  std::is_convertible_v<IndexType0, index_type> and
82  (extents_type::rank() == 1), int> = 0>
83  constexpr index_type
84  operator() (IndexType0 i0) const
85 #endif
86  {
87  if (i0 == 0) return access_with_padded_indices();
88  return nested_mapping_.required_span_size();
89  }
90 
91 #ifdef __cpp_concepts
92  constexpr index_type
93  operator() (
94  std::convertible_to<index_type> auto i0,
95  std::convertible_to<index_type> auto i1,
96  std::convertible_to<index_type> auto...is) const requires (2 + sizeof...(is) == extents_type::rank())
97 #else
98  template<typename IndexType0, typename IndexType1, typename...IndexTypes, std::enable_if_t<
99  std::is_convertible_v<IndexType0, index_type> and
100  std::is_convertible_v<IndexType1, index_type> and
101  (... and std::is_convertible_v<IndexTypes, index_type>) and
102  (2 + sizeof...(IndexTypes) == extents_type::rank()), int> = 0>
103  constexpr index_type
104  operator() (IndexType0 i0, IndexType1 i1, IndexTypes...is) const
105 #endif
106  {
107  if (i0 == i1) return access_with_padded_indices(i1, is...);
108  return nested_mapping_.required_span_size();
109  }
110 
111  constexpr index_type
112  required_span_size() const noexcept
113  {
114  auto s = nested_mapping_.required_span_size();
115  return s == 0 ? 0 : s + 1;
116  }
117 
118  static constexpr bool
119  is_always_unique() noexcept
120  {
121  if constexpr (not nested_mapping_type::is_always_unique()) return false;
122  else if constexpr (extents_type::rank() == 0) return true;
123  else if constexpr (extents_type::rank() == 1) return extents_type::static_extent(0) == 1;
124  else return extents_type::static_extent(0) == 1 and extents_type::static_extent(1) == 1;
125  }
126 
127  static constexpr bool
128  is_always_exhaustive() noexcept { return nested_mapping_type::is_always_exhaustive(); }
129 
130  static constexpr bool
131  is_always_strided() noexcept { return false; }
132 
133  constexpr bool
134  is_unique() const
135  {
136  if (not nested_mapping_type::is_unique()) return false;
137  if constexpr (extents_type::rank() == 0) return true;
138  else if constexpr (extents_type::rank() == 1) return extents_.extent(0) == 1;
139  else return extents_.extent(0) == 1 and extents_.extent(1) == 1;
140  }
141 
142  constexpr bool
143  is_exhaustive() const { return nested_mapping_type::is_exhaustive(); }
144 
145  constexpr bool
146  is_strided() const { return false; }
147 
148  constexpr index_type
149  stride(std::size_t r) const
150  {
151  assert(false);
152  return 0;
153  }
154 
155  template<class OtherExtents>
156  friend constexpr bool
157  operator==(const mapping& lhs, const mapping<OtherExtents>& rhs) noexcept
158  {
159  return patterns::compare_pattern_collections(lhs.extents(), rhs.extents());
160  }
161 
162  private:
163 
164  nested_mapping_type nested_mapping_;
165  extents_type extents_;
166 
167  };
168  };
169 
170 
176  template<typename NestedAccessor>
178  {
180  using reference = element_type;
181  using data_handle_type = std::tuple<typename NestedAccessor::data_handle_type, std::size_t>;
183 
184  static_assert(values::value<element_type>);
185 #ifdef __cpp_concepts
186  static_assert(requires { static_cast<reference>(std::declval<int>()); });
187  static_assert(requires { static_cast<reference>(std::declval<typename NestedAccessor::reference>()); });
188 #endif
189 
194  constexpr
195  to_diagonal_accessor(NestedAccessor acc) : nested_accessor_(std::move(acc)) {}
196 
197  to_diagonal_accessor() = delete;
198 
199 #ifdef __cpp_concepts
200  template<stdex::convertible_to<NestedAccessor> OtherNestedAccessor> requires
201  (not std::is_same_v<NestedAccessor, OtherNestedAccessor>)
202 #else
203  template<typename OtherNestedAccessor, std::enable_if_t<
204  stdex::convertible_to<OtherNestedAccessor, NestedAccessor> and
205  (not std::is_same_v<NestedAccessor, OtherNestedAccessor>), int> = 0>
206 #endif
207  constexpr to_diagonal_accessor(const to_diagonal_accessor<OtherNestedAccessor>& other) noexcept
208  : nested_accessor_ {other.element_} {}
209 
210 #ifdef __cpp_concepts
211  template<stdex::convertible_to<NestedAccessor> OtherNestedAccessor> requires
212  (not std::is_same_v<NestedAccessor, OtherNestedAccessor>)
213 #else
214  template<typename OtherNestedAccessor, std::enable_if_t<
215  stdex::convertible_to<OtherNestedAccessor, NestedAccessor> and
216  (not std::is_same_v<NestedAccessor, OtherNestedAccessor>), int> = 0>
217 #endif
219  : nested_accessor_ {std::move(other).element_} {}
220 
221  constexpr reference
222  access(data_handle_type p, std::size_t i) const noexcept
223  {
224  if (i == std::get<1>(p)) return static_cast<reference>(0);
225  return static_cast<reference>(nested_accessor_.access(std::get<0>(std::move(p)), i));
226  }
227 
228  constexpr data_handle_type
229  offset(data_handle_type p, std::size_t i) const noexcept
230  {
231  if (i == 0) return p;
232  return {std::get<0>(std::move(p)), std::get<1>(p) - i};
233  }
234 
235  const NestedAccessor&
236  nested_accessor() const noexcept { return nested_accessor_; }
237 
238  private:
239 
240  NestedAccessor nested_accessor_;
241 
242  };
243 
244 
245 }
246 
247 #endif
Definition: basics.hpp:41
typename value_type_of< T >::type value_type_of_t
Helper template for value_type_of.
Definition: value_type_of.hpp:52
Definition: to_diagonal_mdspan_policies.hpp:29
constexpr to_diagonal_accessor(NestedAccessor acc)
Definition: to_diagonal_mdspan_policies.hpp:195
decltype(auto) constexpr access(Arg &&arg, const Indices &indices)
Access a component of an indexible object at a given set of indices.
Definition: access.hpp:74
constexpr auto compare_pattern_collections(const A &a, const B &b)
Compare each element of two pattern_collection objects lexicographically.
Definition: compare_pattern_collections.hpp:137
Definition: to_diagonal_mdspan_policies.hpp:177
Definition: to_diagonal_mdspan_policies.hpp:32