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