OpenKalman
randomize.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-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_RANDOMIZE_HPP
17 #define OPENKALMAN_RANDOMIZE_HPP
18 
19 namespace OpenKalman
20 {
21  // ----------- //
22  // randomize //
23  // ----------- //
24 
25  namespace detail
26  {
27 #ifndef __cpp_concepts
28  template<typename T, typename = void, typename = void>
29  struct is_std_dist : std::false_type {};
30 
31  template<typename T>
32  struct is_std_dist<T, std::void_t<typename T::result_type>, std::void_t<typename T::param_type>> : std::true_type {};
33 #endif
34 
35 
36  template<typename random_number_generator>
38  {
39  static auto& get()
40  {
41  static std::random_device rd;
42  static std::decay_t<random_number_generator> gen {rd()};
43  return gen;
44  }
45  };
46 
47 
48  template<typename random_number_generator, typename distribution_type>
49  struct RandomizeOp
50  {
51  template<typename G, typename D>
52  RandomizeOp(G& g, D&& d) : generator{g}, distribution{std::forward<D>(d)} {}
53 
54  auto operator()() const
55  {
56  if constexpr (std::is_arithmetic_v<distribution_type>)
57  return distribution;
58  else
59  return distribution(generator);
60  }
61 
62  private:
63 
64  std::decay_t<random_number_generator>& generator;
65  mutable std::decay_t<distribution_type> distribution;
66  };
67 
68 
69  template<typename G, typename D>
70  RandomizeOp(G&, D&&) -> RandomizeOp<G, D>;
71 
72  } // namespace detail
73 
74 
120 #ifdef __cpp_concepts
121  template<indexible PatternMatrix, std::size_t...indices, std::uniform_random_bit_generator random_number_generator,
122  coordinates::pattern...Ds, typename...Dists>
123  requires ((fixed_pattern<std::tuple_element_t<indices, std::tuple<Ds...>>>) and ...) and
124  (sizeof...(Dists) == (1 * ... * coordinates::dimension_of_v<std::tuple_element_t<indices, std::tuple<Ds...>>>)) and
125  ((std::is_arithmetic_v<std::decay_t<Dists>> or
126  requires { typename std::decay_t<Dists>::result_type; typename std::decay_t<Dists>::param_type; }) and ...)
127 #else
128  template<typename PatternMatrix, std::size_t...indices, typename random_number_generator, typename...Ds,
129  typename...Dists, std::enable_if_t<indexible<PatternMatrix> and (coordinates::pattern<Ds> and ...) and
130  ((fixed_pattern<std::tuple_element_t<indices, std::tuple<Ds...>>>) and ...) and
131  (sizeof...(Dists) == (1 * ... * coordinates::dimension_of<std::tuple_element_t<indices, std::tuple<Ds...>>>::value)) and
132  ((std::is_arithmetic_v<std::decay_t<Dists>> or detail::is_std_dist<std::decay_t<Dists>>::value) and ...), int> = 0>
133 #endif
134  constexpr auto
135  randomize(random_number_generator& gen, const std::tuple<Ds...>& ds_tuple, Dists&&...dists)
136  {
137  auto ret {n_ary_operation<PatternMatrix, indices...>(ds_tuple, detail::RandomizeOp {gen, (std::forward<Dists>(dists))}...)};
138  if constexpr (sizeof...(Dists) == 1) return to_dense_object(std::move(ret));
139  else return ret;
140  }
141 
142 
147 #ifdef __cpp_concepts
148  template<indexible PatternMatrix, std::size_t...indices, coordinates::pattern...Ds, typename...Dists>
149  requires ((fixed_pattern<std::tuple_element_t<indices, std::tuple<Ds...>>>) and ...) and
150  (sizeof...(Dists) == (1 * ... * coordinates::dimension_of_v<std::tuple_element_t<indices, std::tuple<Ds...>>>)) and
151  ((std::is_arithmetic_v<std::decay_t<Dists>> or
152  requires { typename std::decay_t<Dists>::result_type; typename std::decay_t<Dists>::param_type; }) and ...)
153 #else
154  template<typename PatternMatrix, std::size_t...indices, typename...Ds, typename...Dists,
155  std::enable_if_t<indexible<PatternMatrix> and (coordinates::pattern<Ds> and ...) and
156  ((fixed_pattern<std::tuple_element_t<indices, std::tuple<Ds...>>>) and ...) and
157  (sizeof...(Dists) == (1 * ... * coordinates::dimension_of<std::tuple_element_t<indices, std::tuple<Ds...>>>::value)) and
158  ((std::is_arithmetic_v<std::decay_t<Dists>> or detail::is_std_dist<std::decay_t<Dists>>::value) and ...), int> = 0>
159 #endif
160  constexpr auto
161  randomize(const std::tuple<Ds...>& d_tuple, Dists&&...dists)
162  {
164  return randomize<PatternMatrix, indices...>(gen, d_tuple, std::forward<Dists>(dists)...);
165  }
166 
167 
202 #ifdef __cpp_concepts
203  template<indexible PatternMatrix, std::size_t...indices, std::uniform_random_bit_generator random_number_generator,
204  typename...Dists>
205  requires (not has_dynamic_dimensions<PatternMatrix>) and
206  (sizeof...(Dists) == (1 * ... * index_dimension_of_v<PatternMatrix, indices>)) and
207  ((std::is_arithmetic_v<Dists> or requires { typename Dists::result_type; typename Dists::param_type; }) and ...)
208 #else
209  template<typename PatternMatrix, std::size_t...indices, typename random_number_generator, typename...Dists,
210  std::enable_if_t<indexible<PatternMatrix> and (not has_dynamic_dimensions<PatternMatrix>) and
211  (sizeof...(Dists) == (1 * ... * index_dimension_of<PatternMatrix, indices>::value)) and
212  ((std::is_arithmetic_v<Dists> or detail::is_std_dist<Dists>::value) and ...), int> = 0>
213 #endif
214  constexpr auto
215  randomize(random_number_generator& gen, Dists&&...dists)
216  {
217  auto d_tup = all_vector_space_descriptors<PatternMatrix>();
218  return randomize<PatternMatrix, indices...>(gen, d_tup, std::forward<Dists>(dists)...);
219  }
220 
221 
226 #ifdef __cpp_concepts
227  template<indexible PatternMatrix, std::size_t...indices, typename...Dists>
228  requires (not has_dynamic_dimensions<PatternMatrix>) and
229  (sizeof...(Dists) == (1 * ... * index_dimension_of_v<PatternMatrix, indices>)) and
230  ((std::is_arithmetic_v<Dists> or requires { typename Dists::result_type; typename Dists::param_type; }) and ...)
231 #else
232  template<typename PatternMatrix, std::size_t...indices, typename...Dists, std::enable_if_t<
233  indexible<PatternMatrix> and (not has_dynamic_dimensions<PatternMatrix>) and
234  (sizeof...(Dists) == (1 * ... * index_dimension_of<PatternMatrix, indices>::value)) and
235  ((std::is_arithmetic_v<Dists> or detail::is_std_dist<Dists>::value) and ...), int> = 0>
236 #endif
237  constexpr auto
238  randomize(Dists&&...dists)
239  {
241  return randomize<PatternMatrix, indices...>(gen, std::forward<Dists>(dists)...);
242  }
243 
244 
245 } // namespace OpenKalman
246 
247 #endif //OPENKALMAN_RANDOMIZE_HPP
constexpr auto n_ary_operation(const std::tuple< Ds... > &d_tup, Operation &&operation, Args &&...args)
Perform a component-wise n-ary operation, using broadcasting to match the size of a pattern matrix...
Definition: n_ary_operation.hpp:319
Definition: randomize.hpp:49
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 to_dense_object(Arg &&arg)
Convert the argument to a dense, writable matrix of a particular scalar type.
Definition: to_dense_object.hpp:37
The size of a coordinates::pattern.
Definition: dimension_of.hpp:37
The root namespace for OpenKalman.
Definition: basics.hpp:34
Definition: randomize.hpp:37
Definition: randomize.hpp:29
auto randomize(Dists &&... dists)
Fill a fixed-shape typed matrix with random values selected from a random distribution.
Definition: typed-matrix-overloads.hpp:817
The dimension of an index for a matrix, expression, or array.
Definition: index_dimension_of.hpp:34
constexpr bool distribution
T is a statistical distribution of any kind that is defined in OpenKalman.
Definition: object-types.hpp:193