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 detail
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  }
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 collections::collection_element_t<sizeof...(Factors) - 1, std::tuple<Factors...>>::value == 1; })
57 #else
58  else if constexpr (detail::FactorIs1<collections::collection_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 }
81 
82 #endif
constexpr bool indexible
T is a multidimensional array type.
Definition: indexible.hpp:32
constexpr bool value
T is a fixed or dynamic value that is reducible to a number.
Definition: value.hpp:45
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
decltype(auto) constexpr apply(F &&f, T &&t)
A generalization of std::apply.
Definition: apply.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:42
Inclusion file for collections.
typename collection_element< i, T >::type collection_element_t
Helper template for collection_element.
Definition: collection_element.hpp:116
constexpr bool index
T is an index value.
Definition: index.hpp:62
Definition: broadcast.hpp:27