OpenKalman
get_slice.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) 2022 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_GET_SLICE_HPP
17 #define OPENKALMAN_GET_SLICE_HPP
18 
19 namespace OpenKalman
20 {
21 
22  namespace detail
23  {
24  template<bool is_offset, std::size_t arg_ix, typename Arg>
25  constexpr auto get_block_limits(const Arg& arg)
26  {
27  if constexpr (is_offset) return std::integral_constant<std::size_t, 0>{};
28  else if constexpr (dynamic_dimension<Arg, arg_ix>) return get_index_dimension_of<arg_ix>(arg);
29  else return std::integral_constant<std::size_t, index_dimension_of_v<Arg, arg_ix>>{};
30  }
31 
32 
33  template<bool is_offset, std::size_t arg_ix, std::size_t index, std::size_t...indices, typename Arg, typename Limit, typename...Limits>
34  constexpr auto get_block_limits(const Arg& arg, const Limit& limit, const Limits&...limits)
35  {
36  if constexpr (arg_ix == index)
37  {
38  static_assert(((index != indices) and ...), "Duplicate index parameters are not allowed in block function.");
39  return limit;
40  }
41  else
42  {
43  return get_block_limits<is_offset, arg_ix, indices...>(arg, limits...);
44  }
45  }
46 
47 
48  template<bool is_offset, std::size_t...indices, typename Arg, typename Limit_tup, std::size_t...arg_ix, std::size_t...limits_ix>
49  constexpr auto expand_block_limits(std::index_sequence<arg_ix...>, std::index_sequence<limits_ix...>, const Arg& arg, const Limit_tup& limit_tup)
50  {
51  return std::tuple {get_block_limits<is_offset, arg_ix, indices...>(arg, std::get<limits_ix>(limit_tup)...)...};
52  }
53 
54 
55  template<typename Arg, typename...Offset, typename...Extent, std::size_t...Ix>
56  constexpr auto get_slice_impl(Arg&& arg, const std::tuple<Offset...>& offsets, const std::tuple<Extent...>& extents, std::index_sequence<Ix...> seq)
57  {
58  auto slice_descriptors = std::tuple {
59  get_slice<scalar_type_of_t<Arg>>(get_vector_space_descriptor<Ix>(std::forward<Arg>(arg)), std::get<Ix>(offsets), std::get<Ix>(extents))...};
60 
61  if constexpr (constant_matrix<Arg>)
62  {
63  return make_constant<Arg>(constant_coefficient{arg}, std::move(slice_descriptors));
64  }
65  else
66  {
68  interface::library_interface<std::decay_t<Arg>>::get_slice(std::forward<Arg>(arg), offsets, extents),
69  std::move(slice_descriptors));
70  }
71  // \todo If arg is directly_accessible and the library interface is not defined, extract the block from the raw data.
72  }
73 
74  } // namespace detail
75 
76 
89 #ifdef __cpp_concepts
90  template<std::size_t...indices, indexible Arg, values::index...Offset, values::index...Extent> requires
91  (sizeof...(Offset) == sizeof...(Extent)) and internal::has_uniform_static_vector_space_descriptors<Arg, indices...> and
92  (sizeof...(indices) == 0 or sizeof...(indices) == sizeof...(Offset))
93  constexpr indexible decltype(auto)
94 #else
95  template<std::size_t...indices, typename Arg, typename...Offset, typename...Extent, std::enable_if_t<
96  indexible<Arg> and (values::index<Offset> and ...) and (values::index<Extent> and ...) and
97  (sizeof...(Offset) == sizeof...(Extent)) and internal::has_uniform_static_vector_space_descriptors<Arg, indices...> and
98  (sizeof...(indices) == 0 or sizeof...(indices) == sizeof...(Offset)), int> = 0>
99  constexpr decltype(auto)
100 #endif
101  get_slice(Arg&& arg, const std::tuple<Offset...>& offsets, const std::tuple<Extent...>& extents)
102  {
103  if constexpr (sizeof...(Offset) == 0)
104  {
105  return std::forward<Arg>(arg);
106  }
107  else
108  {
109  std::index_sequence_for<Offset...> offset_seq;
110  std::conditional_t<sizeof...(indices) == 0, decltype(offset_seq), std::index_sequence<indices...>> indices_seq;
111  internal::check_block_limits(offset_seq, indices_seq, arg, offsets);
112  internal::check_block_limits(offset_seq, indices_seq, arg, offsets, extents);
113 
114  if constexpr (sizeof...(indices) == 0)
115  {
116  return detail::get_slice_impl(std::forward<Arg>(arg), offsets, extents, offset_seq);
117  }
118  else
119  {
120  auto arg_ix_seq = std::make_index_sequence<index_count_v<Arg>>{};
121  return detail::get_slice_impl(std::forward<Arg>(arg),
122  detail::expand_block_limits<true, indices...>(arg_ix_seq, offset_seq, arg, offsets),
123  detail::expand_block_limits<false, indices...>(arg_ix_seq, offset_seq, arg, extents),
124  offset_seq);
125  }
126  }
127  }
128 
129 } // namespace OpenKalman
130 
131 #endif //OPENKALMAN_GET_SLICE_HPP
auto make_vector_space_adapter(Arg &&arg, Descriptors &&descriptors)
If necessary, wrap an object in a wrapper that adds vector space descriptors for each index...
Definition: make_vector_space_adapter.hpp:37
decltype(auto) constexpr get_slice(Arg &&arg, const std::tuple< Offset... > &offsets, const std::tuple< Extent... > &extents)
Extract a slice from a matrix or tensor.
Definition: get_slice.hpp:101
constexpr bool indexible
T is a generalized tensor type.
Definition: indexible.hpp:32
The root namespace for OpenKalman.
Definition: basics.hpp:34
constexpr bool index
T is an index value.
Definition: index.hpp:56
constant_coefficient(const T &) -> constant_coefficient< T >
Deduction guide for constant_coefficient.
constexpr bool index
An object describing a collection of /ref values::index objects.
Definition: index.hpp:75