OpenKalman
broadcast.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) 2024 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_BROADCAST_HPP
17 #define OPENKALMAN_BROADCAST_HPP
18 
20 
21 namespace OpenKalman
22 {
23 #ifndef __cpp_concepts
24  namespace details
25  {
26  template<typename Factor, typename = void>
27  struct FactorIs1 : std::false_type {};
28 
29  template<typename Factor>
30  struct FactorIs1<Factor, std::enable_if_t<Factor::value == 1>> : std::true_type {};
31  } // namespace details
32 #endif
33 
42 #ifdef __cpp_concepts
43  template<indexible Arg, values::index...Factors>
44  constexpr indexible decltype(auto)
45 #else
46  template<typename Arg, typename...Factors, std::enable_if_t<indexible<Arg> and (... and values::index<Factors>), int> = 0>
47  constexpr decltype(auto)
48 #endif
49  broadcast(Arg&& arg, const Factors&...factors)
50  {
51  if constexpr (sizeof...(Factors) == 0)
52  {
53  return std::forward<Arg>(arg);
54  }
55 #ifdef __cpp_concepts
56  else if constexpr (requires { requires std::tuple_element_t<sizeof...(Factors) - 1, std::tuple<Factors...>>::value == 1; })
57 #else
58  else if constexpr (details::FactorIs1<std::tuple_element_t<sizeof...(Factors) - 1, std::tuple<Factors...>>>::value)
59 #endif
60  {
61  // Recursively remove any trailing 1D vector space descriptors
62  return std::apply(
63  [](Arg&& arg, const auto&...fs) { return broadcast(std::forward<Arg>(arg), fs...); },
64  collections::views_concat(std::forward_as_tuple(std::forward<Arg>(arg)),
65  internal::tuple_slice<0, sizeof...(Factors) - 1>(std::forward_as_tuple(factors...))));
66  }
67  else
68  {
69  if constexpr ((... or values::dynamic<Factors>))
70  {
71  if ((... or (factors <= 0))) throw std::invalid_argument {"In broadcast, all factors must be positive"};
72  }
73 
75  return Trait::broadcast(std::forward<Arg>(arg), factors...);
76  }
77  }
78 
79 
80 } // namespace OpenKalman
81 
82 #endif //OPENKALMAN_BROADCAST_HPP
Definition of collections::concat_tuple_view and collections::views::concat.
Definition: broadcast.hpp:27
constexpr bool indexible
T is a generalized tensor type.
Definition: indexible.hpp:32
Definition: tuple_reverse.hpp:103
constexpr bool value
T is numerical value or is reducible to a numerical value.
Definition: value.hpp:31
decltype(auto) constexpr broadcast(Arg &&arg, const Factors &...factors)
Broadcast an object by replicating it by factors specified for each index.
Definition: broadcast.hpp:49
The root namespace for OpenKalman.
Definition: basics.hpp:34
An interface to various routines from the linear algebra library associated with indexible object T...
Definition: library_interface.hpp:37
constexpr bool index
T is an index value.
Definition: index.hpp:56
constexpr auto tuple_slice(Arg &&arg)
Takes a slice of a tuple, given an index range.
Definition: tuple_slice.hpp:132