16 #ifndef OPENKALMAN_SAMPLEPOINTSTRANSFORM_HPP 17 #define OPENKALMAN_SAMPLEPOINTSTRANSFORM_HPP 36 template<
typename SamplePo
intsType>
46 template<
typename SamplePo
intsType>
53 template<
typename T, std::size_t...ints>
54 static constexpr
auto count_dim_impl(std::index_sequence<ints...>)
56 return (0 + ... + index_dimension_of_v<std::tuple_element_t<1 + ints, T>, 0>);
61 template<
typename In,
typename...Ts>
62 static constexpr
auto count_dim()
64 return (index_dimension_of_v<In, 0> + ... +
65 count_dim_impl<Ts>(std::make_index_sequence<std::tuple_size_v<Ts> - 1> {}));
70 template<std::size_t pos = 0,
typename T,
typename...Ts,
typename FlattenedPs>
71 static auto construct_ps(FlattenedPs&& flattened_ps)
73 constexpr
auto group_size = std::tuple_size_v<std::decay_t<T>> - 1;
74 return std::tuple_cat(
75 oin::tuple_slice<pos, pos + group_size>(std::forward<FlattenedPs>(flattened_ps)),
76 construct_ps<pos + group_size, Ts...>(std::forward<FlattenedPs>(flattened_ps)));
81 template<std::
size_t pos = 0,
typename FlattenedPs>
82 static auto construct_ps(FlattenedPs&& flattened_ps)
84 static_assert(pos == std::tuple_size_v<FlattenedPs>);
89 template<
typename G,
typename Dists,
typename Points, std::size_t...ints>
90 static constexpr
auto y_means_impl(
const G& g,
const Dists& dists,
const Points& points, std::index_sequence<ints...>)
92 constexpr
auto count = index_dimension_of_v<decltype(std::get<0>(points)), 1>;
93 return apply_columnwise<count>([&](std::size_t i) {
94 return g((column(std::get<ints>(points), i) + mean_of(std::get<ints>(dists)))...);
115 #ifdef __cpp_concepts 116 template<std::size_t dim,
typename InputDist,
bool return_cross, std::size_t i = 0,
117 typename Gs,
typename D,
typename Ds,
typename P,
typename Ps> requires
118 (std::tuple_size_v<std::decay_t<Gs>> == std::tuple_size_v<std::decay_t<Ds>>) and
119 (
std::tuple_size_v<
std::decay_t<Gs>> ==
std::tuple_size_v<
std::decay_t<Ps>>)
121 template<std::size_t dim,
typename InputDist,
bool return_cross, std::size_t i = 0,
122 typename Gs,
typename D,
typename Ds,
typename P,
typename Ps, std::enable_if_t<
123 (std::tuple_size_v<std::decay_t<Gs>> == std::tuple_size_v<std::decay_t<Ds>>) and
124 (std::tuple_size_v<std::decay_t<Gs>> == std::tuple_size_v<std::decay_t<Ps>>),
int> = 0>
126 static auto transform_impl(Gs&& gs, D&& d, Ds&& ds, P&& p, Ps&& ps)
128 auto g = std::get<i>(std::forward<Gs>(gs));
130 auto xdists_tup = std::tuple_cat(std::forward_as_tuple(std::forward<D>(d)), std::get<i>(std::forward<Ds>(ds)));
132 auto xpoints_tup = std::tuple_cat(std::forward_as_tuple(p), std::get<i>(std::forward<Ps>(ps)));
134 constexpr std::size_t N = std::tuple_size_v<decltype(xpoints_tup)>;
135 static_assert(N == std::tuple_size_v<decltype(xdists_tup)>);
137 auto y_means =
Mean { y_means_impl(g, std::move(xdists_tup), std::move(xpoints_tup), std::make_index_sequence<N> {})};
142 auto ypoints = apply_columnwise(
143 [&](
const auto& col) {
return make_self_contained(col - y_mean);}, std::move(y_means));
145 if constexpr (i + 1 < std::tuple_size_v<std::decay_t<Gs>>)
147 auto y_covariance = SamplePointsType::template covariance<dim, InputDist, false>(std::forward<P>(p), ypoints);
148 auto y =
GaussianDistribution {make_self_contained(std::move(y_mean)), std::move(y_covariance)};
149 return transform_impl<dim, InputDist, return_cross, i + 1>(
150 std::forward<Gs>(gs), std::move(y), std::forward<Ds>(ds), std::move(ypoints), std::forward<Ps>(ps));
154 auto y_covariance = SamplePointsType::template covariance<dim, InputDist, return_cross>(
155 std::forward<P>(p), std::move(ypoints));
157 if constexpr (return_cross)
159 auto [y_cov, cross] = std::move(y_covariance);
160 return std::tuple {
GaussianDistribution {make_self_contained(std::move(y_mean)), std::move(y_cov)},
181 template<
bool return_cross,
typename InputDist,
typename...Ts>
182 auto transform(InputDist&& x, Ts&&...ts)
const 184 static_assert(
sizeof...(Ts) > 0);
187 auto flattened_ds = std::tuple_cat(
oin::tuple_slice<1, std::tuple_size_v<std::decay_t<Ts>>>(ts)...);
190 auto points_tuple = std::apply([](
const auto&...args) {
191 return SamplePointsType::sample_points(args...);
192 }, std::tuple_cat(std::forward_as_tuple(x), std::move(flattened_ds)));
195 auto p = std::get<0>(std::move(points_tuple));
198 auto flattened_ps = oin::tuple_slice<1, std::tuple_size_v<decltype(points_tuple)>>(std::move(points_tuple));
201 auto ps = construct_ps<0, Ts...>(std::move(flattened_ps));
204 auto gs = std::forward_as_tuple(std::get<0>(std::forward<Ts>(ts))...);
207 auto ds = std::tuple {oin::tuple_slice<1, std::tuple_size_v<std::decay_t<Ts>>>(std::forward<Ts>(ts))...};
210 constexpr
auto dim = count_dim<InputDist, Ts...>();
212 return SamplePointsTransform::transform_impl<dim, InputDist, return_cross>(
213 std::move(gs), std::forward<InputDist>(x), std::move(ds), std::move(p), std::move(ps));
225 #ifdef __cpp_concepts 228 template<
typename InputDist,
typename...Ts, std::enable_if_t<
233 return transform<false>(std::forward<InputDist>(x), std::forward<Ts>(ts)...);
244 #ifdef __cpp_concepts 246 requires(Trans g, InputDist x, NoiseDists...n) { g(mean_of(x), mean_of(n)...); }
248 template<
typename InputDist,
typename Trans,
typename ... NoiseDists, std::enable_if_t<
249 (gaussian_distribution<InputDist> and ... and gaussian_distribution<NoiseDists>) and
253 auto operator()(InputDist&& x, Trans&& g, NoiseDists&&...n)
const 255 return transform<false>(
256 std::forward<InputDist>(x), std::forward_as_tuple(std::forward<Trans>(g), std::forward<NoiseDists>(n)...));
267 #ifdef __cpp_concepts 270 template<
typename InputDist,
typename...Ts, std::enable_if_t<
275 return transform<true>(std::forward<InputDist>(x), std::forward<Ts>(ts)...);
286 #ifdef __cpp_concepts 288 requires(Trans g, InputDist x, NoiseDists...n) { g(mean_of(x), mean_of(n)...); }
290 template<
typename InputDist,
typename Trans,
typename ... NoiseDists, std::enable_if_t<
291 (gaussian_distribution<InputDist> and ... and gaussian_distribution<NoiseDists>) and
297 return transform<true>(
298 std::forward<InputDist>(x), std::forward_as_tuple(std::forward<Trans>(g), std::forward<NoiseDists>(n)...));
306 #endif //OPENKALMAN_SAMPLEPOINTSTRANSFORM_HPP Definition for collections::tuple_like.
decltype(auto) constexpr from_euclidean(Arg &&arg, const V &v)
Project the Euclidean vector space associated with index 0 to coordinates::pattern v after applying d...
Definition: from_euclidean.hpp:35
A set of one or more column vectors, each representing a statistical mean.
Definition: forward-class-declarations.hpp:477
Definition: tuple_reverse.hpp:103
A Gaussian distribution, defined in terms of a Mean and a Covariance.
Definition: GaussianDistribution.hpp:42
The root namespace for OpenKalman.
Definition: basics.hpp:34
decltype(auto) constexpr to_euclidean(Arg &&arg)
Project the vector space associated with index 0 to a Euclidean space for applying directional statis...
Definition: to_euclidean.hpp:38
constexpr bool gaussian_distribution
T is a Gaussian distribution.
Definition: object-types.hpp:182
constexpr auto tuple_slice(Arg &&arg)
Takes a slice of a tuple, given an index range.
Definition: tuple_slice.hpp:132
Mean(V &&) -> Mean< Dimensions< index_dimension_of_v< V, 0 >>, passable_t< V >>
Deduce template parameters from a typed_matrix_nestable, assuming untyped coordinates::pattern.
Definition: basics.hpp:48
constexpr bool tuple_like
T is a non-empty tuple, pair, array, or other type that acts like a tuple.
Definition: tuple_like.hpp:51