16 #ifndef OPENKALMAN_GAUSSIANDISTRIBUTION_HPP 17 #define OPENKALMAN_GAUSSIANDISTRIBUTION_HPP 20 #include <adapters/details/adapters-interface.hpp> 30 std::uniform_random_bit_generator random_number_engine> requires
31 (index_dimension_of_v<MeanNestedMatrix, 0> == index_dimension_of_v<CovarianceNestedMatrix, 0>) and
32 (index_dimension_of_v<MeanNestedMatrix, 1> == 1) and
37 typename StaticDescriptor,
38 typename MeanNestedMatrix,
39 typename CovarianceNestedMatrix,
40 typename random_number_engine>
45 #ifndef __cpp_concepts 46 static_assert(typed_matrix_nestable<MeanNestedMatrix>);
47 static_assert(covariance_nestable<CovarianceNestedMatrix>);
48 static_assert(index_dimension_of_v<MeanNestedMatrix, 0> == index_dimension_of_v<CovarianceNestedMatrix, 0>);
49 static_assert(index_dimension_of_v<MeanNestedMatrix, 1> == 1);
56 static constexpr
auto dim = coordinates::dimension_of_v<StaticDescriptor>;
63 template<
typename Arg>
64 static decltype(
auto) cov_adapter(Arg&& arg)
66 if constexpr (triangular_covariance<Arg>)
return square(std::forward<Arg>(arg));
67 else return std::forward<Arg>(arg);
80 GaussianDistribution() requires std::default_initializable<Mean> and std::default_initializable<Covariance>
82 template<
typename T = Mean,
typename U = Covariance, std::enable_if_t<
83 std::is_default_constructible_v<T> and std::is_default_constructible_v<U>,
int> = 0>
93 template<gaussian_distribution Arg> requires (not std::derived_from<std::decay_t<Arg>,
GaussianDistribution>) and
94 compares_with<typename DistributionTraits<Arg>::StaticDescriptor, StaticDescriptor>
96 template<
typename Arg, std::enable_if_t<gaussian_distribution<Arg> and
97 not std::is_base_of_v<GaussianDistribution, std::decay_t<Arg>> and
98 compares_with<
typename DistributionTraits<Arg>::StaticDescriptor, StaticDescriptor>,
int> = 0>
101 :
mu {std::forward<Arg>(arg).
mu},
sigma {std::forward<Arg>(arg).
sigma} {}
113 #ifdef __cpp_concepts 114 template<typed_matrix M> requires vector<M> and has_untyped_index<M, 1> and
115 compares_with<vector_space_descriptor_of_t<M, 0>, StaticDescriptor>
117 template<
typename M, std::enable_if_t<typed_matrix<M> and vector<M> and has_untyped_index<M, 1> and
118 compares_with<vector_space_descriptor_of_t<M, 0>, StaticDescriptor>,
int> = 0>
126 #ifdef __cpp_concepts 127 template<typed_matrix_nestable M> requires vector<M> and (index_dimension_of_v<M, 0> == dim)
129 template<
typename M, std::enable_if_t<typed_matrix_nestable<M> and vector<M> and
130 (index_dimension_of<M, 0>::value == dim),
int> = 0>
139 #ifdef __cpp_concepts 140 template<
typename Cov> requires ((covariance<Cov> or (typed_matrix<Cov> and square_shaped<Cov>)) and
142 (covariance_nestable<Cov> and index_dimension_of_v<Cov, 0> == dim)
144 template<
typename Cov, std::enable_if_t<(covariance<Cov> or (typed_matrix<Cov> and square_shaped<Cov>)) and
145 compares_with<vector_space_descriptor_of_t<Cov, 0>, StaticDescriptor>,
int> = 0>
148 template<
typename Cov, std::enable_if_t<
159 #ifdef __cpp_concepts 160 template<typed_matrix M,
typename Cov> requires vector<M> and has_untyped_index<M, 1> and
161 compares_with<vector_space_descriptor_of_t<M, 0>, StaticDescriptor> and
162 (covariance<Cov> or typed_matrix<Cov>) and
163 compares_with<vector_space_descriptor_of_t<Cov, 0>, StaticDescriptor>
165 template<
typename M,
typename Cov, std::enable_if_t<typed_matrix<M> and vector<M> and has_untyped_index<M, 1> and
166 compares_with<vector_space_descriptor_of_t<M, 0>, StaticDescriptor> and
167 (covariance<Cov> or typed_matrix<Cov>) and
168 compares_with<vector_space_descriptor_of_t<Cov, 0>, StaticDescriptor>,
int> = 0>
171 :
mu {std::forward<M>(
mean)},
sigma {cov_adapter(std::forward<Cov>(cov))} {}
179 #ifdef __cpp_concepts 180 template<typed_matrix M,
typename Cov> requires vector<M> and has_untyped_index<M, 1> and
181 compares_with<vector_space_descriptor_of_t<M, 0>, StaticDescriptor> and
182 covariance_nestable<Cov> and (index_dimension_of_v<Cov, 0> == dim)
184 template<
typename M,
typename Cov, std::enable_if_t<typed_matrix<M> and vector<M> and has_untyped_index<M, 1> and
185 compares_with<vector_space_descriptor_of_t<M, 0>, StaticDescriptor> and
186 covariance_nestable<Cov> and (index_dimension_of<Cov, 0>::value == dim),
int> = 0>
196 #ifdef __cpp_concepts 197 template<typed_matrix_nestable M,
typename Cov> requires vector<M> and
198 (index_dimension_of_v<M, 0> == dim) and (covariance<Cov> or typed_matrix<Cov>) and
199 coordinates::compares_with<vector_space_descriptor_of_t<Cov, 0>, StaticDescriptor>
201 template<
typename M,
typename Cov, std::enable_if_t<typed_matrix_nestable<M> and vector<M> and
202 (index_dimension_of<M, 0>::value == dim) and (covariance<Cov> or typed_matrix<Cov>) and
203 compares_with<vector_space_descriptor_of_t<Cov, 0>, StaticDescriptor>,
int> = 0>
206 :
mu {std::forward<M>(
mean)},
sigma {cov_adapter(std::forward<Cov>(cov))} {}
214 #ifdef __cpp_concepts 215 template<typed_matrix_nestable M,
typename Cov> requires vector<M> and
216 (index_dimension_of_v<M, 0> == dim) and covariance_nestable<Cov> and
217 (index_dimension_of_v<Cov, 0> == dim)
219 template<
typename M,
typename Cov, std::enable_if_t<typed_matrix_nestable<M> and vector<M> and
220 (index_dimension_of<M, 0>::value == dim) and covariance_nestable<Cov> and
221 (index_dimension_of<Cov, 0>::value == dim),
int> = 0>
227 #ifdef __cpp_concepts 228 template<
typename Cov> requires (covariance<Cov> or (typed_matrix<Cov> and square_shaped<Cov>)) and
229 coordinates::compares_with<vector_space_descriptor_of_t<Cov, 0>, StaticDescriptor>
231 template<
typename Cov, std::enable_if_t<(covariance<Cov> or (typed_matrix<Cov> and square_shaped<Cov>)) and
232 compares_with<vector_space_descriptor_of_t<Cov, 0>, StaticDescriptor>,
int> = 0>
235 mu {[]{ make_zero<MeanNestedMatrix>(get_vector_space_descriptor<0>(cov), Dimensions<1>{}); }()},
236 sigma {cov_adapter(std::forward<Cov>(cov))} {}
240 #ifdef __cpp_concepts 241 template<covariance_nestable Cov> requires (index_dimension_of_v<Cov, 0> == dim)
243 template<
typename Cov, std::enable_if_t<
247 mu {[]{ make_zero<MeanNestedMatrix>(get_vector_space_descriptor<0>(cov), Dimensions<1>{}); }()},
248 sigma {cov_adapter(std::forward<Cov>(cov))}{}
255 #ifdef __cpp_concepts 256 template<gaussian_distribution Arg> requires
257 coordinates::compares_with<typename DistributionTraits<Arg>::StaticDescriptor, StaticDescriptor>
259 template<
typename Arg, std::enable_if_t<gaussian_distribution<Arg> and
260 compares_with<
typename DistributionTraits<Arg>::StaticDescriptor, StaticDescriptor>,
int> = 0>
264 if constexpr (std::is_same_v<std::decay_t<Arg>,
GaussianDistribution>)
if (
this == &arg)
return *
this;
265 mu = std::forward<Arg>(arg).
mu;
266 sigma = std::forward<Arg>(arg).sigma;
287 template<
typename S, std::enable_if_t<std::is_convertible_v<S, const Scalar>,
int> = 0>
288 auto& operator*=(
const S
scale)
290 mu *=
static_cast<const Scalar
>(
scale);
291 sigma.scale(static_cast<const Scalar>(scale));
296 template<
typename S, std::enable_if_t<std::is_convertible_v<S, const Scalar>,
int> = 0>
297 auto& operator/=(
const S scale)
299 mu /=
static_cast<const Scalar
>(
scale);
300 sigma.inverse_scale(static_cast<const Scalar>(scale));
310 template<
typename M,
typename C>
314 using MB = equivalent_self_contained_t<nested_object_of_t<M>>;
315 using CB = equivalent_self_contained_t<nested_object_of_t<C>>;
327 auto norm = randomize<Matrix<StaticDescriptor, Axis, MeanNestedMatrix>, random_number_engine>(
328 std::normal_distribution {0.0, 1.0});
329 auto s = square_root(
sigma);
341 #ifdef __cpp_concepts 342 template<
typed_matrix...Z> requires (
sizeof...(Z) > 0) and
345 template<
typename...Z, std::enable_if_t<(
sizeof...(Z) > 0) and ((typed_matrix<Z> and vector<Z> and
350 static constexpr
auto n =
sizeof...(Z);
352 return -0.5 * (n * (dim *
values::log(2 * numbers::pi_v<long double>) +
360 return 0.5 * (dim * (1 + values::log2(numbers::pi_v<long double>) +
361 Scalar {numbers::log2e_v<long double>}) + values::log2(
determinant(
sigma)));
383 #ifdef __cpp_concepts 384 template<typed_matrix M, self_adjo
int_covariance C>
386 template<
typename M,
typename C, std::enable_if_t<typed_matrix<M> and self_adjo
int_covariance<C>,
int> = 0>
394 #ifdef __cpp_concepts 395 template<typed_matrix M, triangular_covariance C>
397 template<
typename M,
typename C, std::enable_if_t<
398 typed_matrix<M> and triangular_covariance<C>,
int> = 0>
401 vector_space_descriptor_of_t<M, 0>,
402 nested_object_of_t<passable_t<M>>,
406 #ifdef __cpp_concepts 407 template<typed_matrix M, typed_matrix C> requires
410 template<
typename M,
typename C, std::enable_if_t<
411 typed_matrix<M> and typed_matrix<C> and
417 decltype(to_covariance_nestable(
nested_object(std::declval<passable_t<C>>())))>;
420 #ifdef __cpp_concepts 421 template<typed_matrix M, covariance_nestable C>
423 template<
typename M,
typename C, std::enable_if_t<typed_matrix<M> and covariance_nestable<C>,
int> = 0>
426 vector_space_descriptor_of_t<M, 0>,
427 nested_object_of_t<passable_t<M>>,
431 #ifdef __cpp_concepts 432 template<typed_matrix_nestable M, self_adjo
int_covariance C>
434 template<
typename M,
typename C, std::enable_if_t<typed_matrix_nestable<M> and self_adjo
int_covariance<C>,
int> = 0>
442 #ifdef __cpp_concepts 443 template<typed_matrix_nestable M, triangular_covariance C>
445 template<
typename M,
typename C, std::enable_if_t<
446 typed_matrix_nestable<M> and triangular_covariance<C>,
int> = 0>
449 vector_space_descriptor_of_t<C, 0>,
454 #ifdef __cpp_concepts 455 template<typed_matrix_nestable M, typed_matrix C> requires
456 coordinates::compares_with<vector_space_descriptor_of_t<C, 0>, vector_space_descriptor_of_t<C, 1>>
458 template<
typename M,
typename C, std::enable_if_t<typed_matrix_nestable<M> and typed_matrix<C> and
459 compares_with<vector_space_descriptor_of_t<C, 0>, vector_space_descriptor_of_t<C, 1>>,
int> = 0>
464 decltype(to_covariance_nestable(
nested_object(std::declval<passable_t<C>>())))>;
467 #ifdef __cpp_concepts 468 template<typed_matrix_nestable M, covariance_nestable C>
470 template<
typename M,
typename C,
471 std::enable_if_t<typed_matrix_nestable<M> and covariance_nestable<C>,
int> = 0>
474 Dimensions<index_dimension_of_v<M, 0>>,
488 #ifdef __cpp_concepts 489 template<gaussian_distribution D>
491 template<
typename D, std::enable_if_t<gaussian_distribution<D>,
int> = 0>
507 #ifdef __cpp_concepts 508 template<std::uniform_random_bit_generator re = std::mt19937, typed_matrix M,
typename Cov> requires
509 vector<M> and has_untyped_index<M, 1> and square_shaped<Cov> and (covariance<Cov> or typed_matrix<Cov>) and
512 template<
typename re = std::mt19937,
typename M,
typename Cov, std::enable_if_t<(not fixed_pattern<re>) and
513 typed_matrix<M> and vector<M> and has_untyped_index<M, 1> and
514 square_shaped<Cov> and (covariance<Cov> or typed_matrix<Cov>) and
515 (compares_with<vector_space_descriptor_of_t<M, 0>, vector_space_descriptor_of_t<Cov, 0>>),
int> = 0>
520 using C = vector_space_descriptor_of_t<M, 0>;
521 using Mb = passable_t<nested_object_of_t<M>>;
522 using Covb = passable_t<nested_object_of_t<Cov>>;
534 #ifdef __cpp_concepts 535 template<std::uniform_random_bit_generator re = std::mt19937, typed_matrix M,
typename Cov> requires
536 vector<M> and has_untyped_index<M, 1> and
537 square_shaped<Cov> and (covariance_nestable<Cov> or typed_matrix_nestable<Cov>) and
538 (index_dimension_of_v<M, 0> == index_dimension_of_v<Cov, 0>)
540 template<
typename re = std::mt19937,
typename M,
typename Cov, std::enable_if_t<
541 (not fixed_pattern<re>) and typed_matrix<M> and vector<M> and has_untyped_index<M, 1> and
542 square_shaped<Cov> and (covariance_nestable<Cov> or typed_matrix_nestable<Cov>) and
548 using C = vector_space_descriptor_of_t<M, 0>;
549 using Mb = passable_t<nested_object_of_t<M>>;
550 auto c =
nested_object(make_covariance<C>(std::forward<Cov>(cov)));
562 #ifdef __cpp_concepts 563 template<std::uniform_random_bit_generator re = std::mt19937, typed_matrix_nestable M,
typename Cov> requires
564 vector<M> and square_shaped<Cov> and
565 (covariance<Cov> or typed_matrix<Cov> or covariance_nestable<Cov> or typed_matrix_nestable<Cov>) and
566 (index_dimension_of_v<M, 0> == index_dimension_of_v<Cov, 0>)
568 template<
typename re = std::mt19937,
typename M,
typename Cov, std::enable_if_t<
569 (not fixed_pattern<re>) and typed_matrix_nestable<M> and vector<M> and square_shaped<Cov> and
570 (covariance<Cov> or typed_matrix<Cov> or covariance_nestable<Cov> or typed_matrix_nestable<Cov>) and
576 if constexpr(covariance<Cov>)
579 using Covb = passable_t<nested_object_of_t<Cov>>;
582 else if constexpr(typed_matrix<Cov>)
586 using SC = equivalent_self_contained_t<decltype(sc)>;
591 static_assert(covariance_nestable<Cov> or typed_matrix_nestable<Cov>);
592 using C = Dimensions<index_dimension_of_v<M, 0>>;
593 auto c =
nested_object(make_covariance<C>(std::forward<Cov>(cov)));
595 std::forward<M>(
mean), std::move(c));
608 #ifdef __cpp_concepts 609 template<fixed_pattern StaticDescriptor, std::uniform_random_bit_generator re = std::mt19937,
610 typed_matrix_nestable M,
typename Cov> requires vector<M> and (covariance_nestable<Cov> or typed_matrix_nestable<Cov>)
612 template<
typename StaticDescriptor,
typename re = std::mt19937,
typename M,
typename Cov, std::enable_if_t<
613 fixed_pattern<StaticDescriptor> and typed_matrix_nestable<M> and vector<M> and
614 (covariance_nestable<Cov> or typed_matrix_nestable<Cov>),
int> = 0>
619 static_assert(index_dimension_of_v<M, 0> == index_dimension_of_v<Cov, 0>);
620 if constexpr(covariance_nestable<Cov>)
623 std::forward<M>(
mean), std::forward<Cov>(cov));
627 static_assert(typed_matrix_nestable<Cov>);
628 auto c =
nested_object(make_covariance<StaticDescriptor>(std::forward<Cov>(cov)));
630 std::forward<M>(
mean), std::move(c));
642 #ifdef __cpp_concepts 643 template<typed_matrix M, covariance Cov, std::uniform_random_bit_generator re = std::mt19937> requires
644 vector<M> and has_untyped_index<M, 1> and
647 template<
typename M,
typename Cov,
typename re = std::mt19937, std::enable_if_t<
648 typed_matrix<M> and vector<M> and has_untyped_index<M, 1> and covariance<Cov> and
654 using C = vector_space_descriptor_of_t<M, 0>;
667 #ifdef __cpp_concepts 668 template<vector M,
typename Cov, std::uniform_random_bit_generator re = std::mt19937> requires
669 (typed_matrix<M> or typed_matrix_nestable<M>) and has_untyped_index<M, 1> and
670 (covariance<Cov> or covariance_nestable<Cov>) and (not typed_matrix<M> or not covariance<Cov>) and
671 (index_dimension_of_v<M, 0> == index_dimension_of_v<Cov, 0>)
673 template<
typename M,
typename Cov,
typename re = std::mt19937, std::enable_if_t<
674 vector<M> and (typed_matrix<M> or typed_matrix_nestable<M>) and has_untyped_index<M, 1> and
675 (covariance<Cov> or covariance_nestable<Cov>) and (not typed_matrix<M> or not covariance<Cov>) and
681 if constexpr(typed_matrix<M>)
683 using C = vector_space_descriptor_of_t<M, 0>;
686 else if constexpr(covariance<Cov>)
688 using C = vector_space_descriptor_of_t<Cov, 0>;
693 using C = Dimensions<index_dimension_of_v<M, 0>>;
707 #ifdef __cpp_concepts 709 std::uniform_random_bit_generator re = std::mt19937> requires
710 vector<M> and (index_dimension_of_v<M, 0> == index_dimension_of_v<Cov, 0>)
712 template<
typename StaticDescriptor,
typename M,
typename Cov,
typename re = std::mt19937, std::enable_if_t<
713 typed_matrix_nestable<M> and vector<M> and covariance_nestable<Cov> and
729 template<
typename Coeffs,
typename NestedMean,
typename NestedCovariance,
typename re>
734 template<
typename Arg>
735 static constexpr
auto count_indices(
const Arg& arg) {
return std::integral_constant<std::size_t, 1>{}; }
737 template<
typename Arg,
typename N>
740 if constexpr (values::fixed<N>)
742 static_assert(n == 0_uz);
743 if constexpr (not dynamic_dimension<NestedMean, 0>)
return OpenKalman::get_vector_space_descriptor<0>(mean_of(arg));
744 else return OpenKalman::get_vector_space_descriptor<0>(covariance_of(arg));
753 template<
typename Arg>
756 return std::forward<Arg>(arg).
mu;
760 #ifdef __cpp_lib_concepts 761 template<
typename Arg> requires raw_data_defined_for<Mean<Coeffs, NestedMean>>
763 template<
typename Arg, std::enable_if_t<raw_data_defined_for<Mean<Coeffs, NestedMean>>,
int> = 0>
765 static constexpr
auto *
766 raw_data(Arg& arg) {
return internal::raw_data(arg.mu()); }
769 static constexpr
Layout layout = layout_of_v<NestedMean>;
776 template<
typename Coeffs,
typename NestedMean,
typename NestedCovariance,
typename re>
779 using StaticDescriptor = Coeffs;
780 using Mean = Mean<StaticDescriptor, NestedMean>;
781 using Covariance = Covariance<StaticDescriptor, NestedCovariance>;
783 template<
typename S>
using distribution_type = std::normal_distribution<S>;
784 using random_number_engine = re;
786 #ifdef __cpp_concepts 787 template<fixed_pattern C = StaticDescriptor, typed_matrix_nestable M, covariance_nestable Cov> requires
788 vector<M> and (index_dimension_of_v<M, 0> == index_dimension_of_v<Cov, 0>)
790 template<
typename C = StaticDescriptor,
typename M,
typename Cov,
791 std::enable_if_t<fixed_pattern<C> and typed_matrix_nestable<M> and covariance_nestable<Cov> and
796 return make_GaussianDistribution<C, random_number_engine>(std::forward<M>(
mean), std::forward<Cov>(
covariance));
806 #ifdef __cpp_concepts 807 template<gaussian_distribution Arg>
809 template<
typename Arg, std::enable_if_t<gaussian_distribution<Arg>,
int> = 0>
811 constexpr decltype(
auto)
814 return (std::forward<Arg>(arg).
mu);
818 #ifdef __cpp_concepts 819 template<gaussian_distribution Arg>
821 template<
typename Arg, std::enable_if_t<gaussian_distribution<Arg>,
int> = 0>
823 constexpr decltype(
auto)
824 covariance_of(Arg&& arg)
826 return (std::forward<Arg>(arg).
sigma);
830 #ifdef __cpp_concepts 831 template<gaussian_distribution T, std::
size_t dimension = index_dimension_of_v<T, 0>,
832 typename Scalar = scalar_type_of_t<T>, std::convertible_to<std::
size_t>...runtime_dimensions> requires
833 (
sizeof...(runtime_dimensions) == (dimension ==
dynamic_size ? 1 : 0))
837 gaussian_distribution<T> and (
sizeof...(runtime_dimensions) == (dimension ==
dynamic_size ? 1 : 0)) and
838 (std::is_convertible_v<runtime_dimensions, std::size_t> and ...),
int> = 0>
841 make_zero_distribution_like(runtime_dimensions...e)
843 using Coeffs =
typename DistributionTraits<T>::StaticDescriptor;
844 using re = DistributionTraits<T>::random_number_engine;
847 return make_gaussian_distribution<re>>(std::move(m), std::move(c));
851 #ifdef __cpp_concepts 852 template<gaussian_distribution T, std::
size_t dimension = index_dimension_of_v<T, 0>,
853 typename Scalar = scalar_type_of_t<T>, std::convertible_to<std::
size_t>...runtime_dimensions> requires
854 (
sizeof...(runtime_dimensions) == (dimension ==
dynamic_size ? 1 : 0))
856 template<typename T, std::size_t dimension = index_dimension_of<T, 0>::value,
858 gaussian_distribution<T> and (
sizeof...(runtime_dimensions) == (dimension ==
dynamic_size ? 1 : 0)) and
859 (std::is_convertible_v<runtime_dimensions, std::size_t> and ...),
int> = 0>
862 make_normal_distribution_like(runtime_dimensions...e)
864 using Coeffs =
typename DistributionTraits<T>::StaticDescriptor;
865 using re = DistributionTraits<T>::random_number_engine;
868 return make_gaussian_distribution<re>>(std::move(m), std::move(c));
872 #ifdef __cpp_concepts 875 template<
typename D,
typename ... Ds,
876 std::enable_if_t<(gaussian_distribution<D> and ... and gaussian_distribution<Ds>),
int> = 0>
879 concatenate(D&& d, Ds&& ... ds)
881 if constexpr(
sizeof...(Ds) > 0)
883 using re =
typename DistributionTraits<D>::random_number_engine;
884 auto m = concatenate(mean_of(std::forward<D>(d)), mean_of(std::forward<Ds>(ds))...);
885 auto cov = concatenate(covariance_of(std::forward<D>(d)), covariance_of(std::forward<Ds>(ds))...);
886 return make_GaussianDistribution<re>(std::move(m), std::move(cov));
897 template<
typename Dist,
typename Means,
typename Covariances, std::size_t ... ints>
898 inline auto zip_dist(Means&& ms, Covariances&& cs, std::index_sequence<ints...>)
900 using re =
typename DistributionTraits<Dist>::random_number_engine;
901 return std::tuple {make_GaussianDistribution<re>(
902 std::get<ints>(std::forward<Means>(ms)),
903 std::get<ints>(std::forward<Covariances>(cs)))...};
909 #ifdef __cpp_concepts 911 coordinates::compares_with<static_concatenate_t<Cs...>,
typename DistributionTraits<D>::StaticDescriptor,
less_equal<>>
913 template<
typename ... Cs,
typename D, std::enable_if_t<
914 (fixed_pattern<Cs> and ...) and gaussian_distribution<D> and
915 coordinates::compares_with<static_concatenate_t<Cs...>,
typename DistributionTraits<D>::StaticDescriptor,
less_equal<>>,
int> = 0>
920 using Coeffs =
typename DistributionTraits<D>::StaticDescriptor;
921 if constexpr(
sizeof...(Cs) == 1 and compares_with<static_concatenate_t<Cs...>, Coeffs>)
923 return std::tuple(std::forward<D>(d));
928 auto covariances =
split_diagonal<Cs...>(covariance_of(std::forward<D>(d)));
929 return OpenKalman::detail::zip_dist<D>(means, covariances, std::index_sequence_for<Cs...> {});
934 #ifdef __cpp_concepts 935 template<gaussian_distribution Dist>
937 template<
typename Dist, std::enable_if_t<gaussian_distribution<Dist>,
int> = 0>
940 operator<<(std::ostream& os,
const Dist& d)
942 os <<
"mean:" << std::endl << mean_of(d) << std::endl <<
943 "covariance:" << std::endl << covariance_of(d) << std::endl;
952 #ifdef __cpp_concepts 953 template<gaussian_distribution Dist1, gaussian_distribution Dist2> requires
954 coordinates::compares_with<typename DistributionTraits<Dist1>::StaticDescriptor,
typename DistributionTraits<Dist2>::StaticDescriptor>
956 template<
typename Dist1,
typename Dist2, std::enable_if_t<
957 gaussian_distribution<Dist1> and gaussian_distribution<Dist2> and
958 coordinates::compares_with<typename DistributionTraits<Dist1>::StaticDescriptor,
959 typename DistributionTraits<Dist2>::StaticDescriptor>,
int> = 0>
962 operator+(Dist1&& d1, Dist2&& d2)
964 using re =
typename DistributionTraits<Dist1>::random_number_engine;
965 auto m1 = mean_of(std::forward<Dist1>(d1)) + mean_of(std::forward<Dist2>(d2));
966 auto m2 = covariance_of(std::forward<Dist1>(d1)) + covariance_of(std::forward<Dist2>(d2));
967 return make_GaussianDistribution<re>(std::move(m1), std::move(m2));
971 #ifdef __cpp_concepts 972 template<gaussian_distribution Dist1, gaussian_distribution Dist2> requires
973 coordinates::compares_with<typename DistributionTraits<Dist1>::StaticDescriptor,
typename DistributionTraits<Dist2>::StaticDescriptor>
975 template<
typename Dist1,
typename Dist2, std::enable_if_t<
976 gaussian_distribution<Dist1> and gaussian_distribution<Dist2> and
977 coordinates::compares_with<typename DistributionTraits<Dist1>::StaticDescriptor,
978 typename DistributionTraits<Dist2>::StaticDescriptor>,
int> = 0>
981 operator-(Dist1&& d1, Dist2&& d2)
983 using re =
typename DistributionTraits<Dist1>::random_number_engine;
984 auto m1 = mean_of(std::forward<Dist1>(d1)) - mean_of(std::forward<Dist2>(d2));
985 auto m2 = covariance_of(std::forward<Dist1>(d1)) - covariance_of(std::forward<Dist2>(d2));
986 return make_GaussianDistribution<re>(std::move(m1), std::move(m2));
990 #ifdef __cpp_concepts 991 template<typed_matrix A, gaussian_distribution D> requires gaussian_distribution<D> and
992 (not euclidean_transformed<A>) and
995 template<
typename A,
typename D, std::enable_if_t<typed_matrix<A> and gaussian_distribution<D> and
996 (not eucl
idean_transformed<A>) and
997 (compares_with<vector_space_descriptor_of_t<A, 1>,
typename DistributionTraits<D>::StaticDescriptor>),
int> = 0>
1000 operator*(A&& a, D&& d)
1002 using re =
typename DistributionTraits<D>::random_number_engine;
1003 auto m = a * mean_of(std::forward<D>(d));
1004 auto c =
scale(covariance_of(std::forward<D>(d)), std::forward<A>(a));
1005 return make_GaussianDistribution<re>(std::move(m), std::move(c));
1009 #ifdef __cpp_concepts 1010 template<gaussian_distribution Dist, std::convertible_to<const typename DistributionTraits<Dist>::Scalar> S>
1012 template<
typename Dist,
typename S, std::enable_if_t<
1013 gaussian_distribution<Dist> and std::is_convertible_v<S, const typename DistributionTraits<Dist>::Scalar>,
int> = 0>
1016 operator*(Dist&& d, S s)
1018 using re =
typename DistributionTraits<Dist>::random_number_engine;
1019 auto m = mean_of(std::forward<Dist>(d)) * s;
1020 auto c =
scale(covariance_of(std::forward<Dist>(d)), s);
1021 return make_GaussianDistribution<re>(std::move(m), std::move(c));
1025 #ifdef __cpp_concepts 1026 template<gaussian_distribution Dist, std::convertible_to<const typename DistributionTraits<Dist>::Scalar> S>
1028 template<
typename Dist,
typename S, std::enable_if_t<
1029 gaussian_distribution<Dist> and std::is_convertible_v<S, const typename DistributionTraits<Dist>::Scalar>,
int> = 0>
1032 operator*(S s, Dist&& d)
1034 using re =
typename DistributionTraits<Dist>::random_number_engine;
1035 auto m = s * mean_of(std::forward<Dist>(d));
1036 auto c =
scale(covariance_of(std::forward<Dist>(d)), s);
1037 return make_GaussianDistribution<re>(std::move(m), std::move(c));
1041 #ifdef __cpp_concepts 1042 template<gaussian_distribution Dist, std::convertible_to<const typename DistributionTraits<Dist>::Scalar> S>
1044 template<
typename Dist,
typename S, std::enable_if_t<
1045 gaussian_distribution<Dist> and std::is_convertible_v<S, const typename DistributionTraits<Dist>::Scalar>,
int> = 0>
1048 operator/(Dist&& d, S s)
1050 using re =
typename DistributionTraits<Dist>::random_number_engine;
1051 auto m = mean_of(std::forward<Dist>(d)) / s;
1052 auto c =
inverse_scale(covariance_of(std::forward<Dist>(d)), s);
1053 return make_GaussianDistribution<re>(std::move(m), std::move(c));
1058 #endif //OPENKALMAN_GAUSSIANDISTRIBUTION_HPP constexpr auto count_indices(const T &t)
Get the number of indices available to address the components of an indexible object.
Definition: count_indices.hpp:33
typename nested_object_of< T >::type nested_object_of_t
Helper type for nested_object_of.
Definition: nested_object_of.hpp:66
constexpr auto log(const Arg &arg)
Constexpr alternative to the std::log function.
Definition: log.hpp:47
decltype(auto) constexpr contract(A &&a, B &&b)
Matrix multiplication of A * B.
Definition: contract.hpp:54
Definition: indexible_object_traits.hpp:36
GaussianDistribution(Mean &&mean, Cov &&cov)
Construct from an rvalue of a mean and a covariance, typed_matrix, or covariance_nestable.
Definition: GaussianDistribution.hpp:146
typename scalar_type_of< T >::type scalar_type_of_t
helper template for scalar_type_of.
Definition: scalar_type_of.hpp:54
auto make_GaussianDistribution(D &&dist)
Make a Gaussian distribution.
Definition: GaussianDistribution.hpp:494
Definition: tuple_reverse.hpp:103
constexpr bool value
T is numerical value or is reducible to a numerical value.
Definition: value.hpp:31
An upper-right triangular matrix.
Covariance(const Args &...) -> Covariance< Dimensions< static_cast< std::size_t >(values::sqrt(sizeof...(Args)))>, HermitianAdapter< Eigen3::eigen_matrix_t< std::common_type_t< Args... >, static_cast< std::size_t >(values::sqrt(sizeof...(Args))), static_cast< std::size_t >(values::sqrt(sizeof...(Args)))>>>
If the arguments are a sequence of scalars, derive a square, self-adjoint matrix. ...
Type scalar type (e.g., std::float, std::double, std::complex<double>) of a tensor.
Definition: scalar_type_of.hpp:32
constexpr bool triangular_matrix
Specifies that a type is a triangular matrix (upper, lower, or diagonal).
Definition: triangular_matrix.hpp:37
decltype(auto) constexpr transpose(Arg &&arg)
Take the transpose of a matrix.
Definition: transpose.hpp:58
Covariance sigma
The Covariance matrix of the distribution.
Definition: GaussianDistribution.hpp:374
A Gaussian distribution, defined in terms of a Mean and a Covariance.
Definition: GaussianDistribution.hpp:42
constexpr bool typed_matrix_nestable
Specifies a type that is nestable in a general typed matrix (e.g., matrix, mean, or euclidean_mean) ...
Definition: object-types.hpp:253
constexpr bool typed_matrix
Specifies that T is a typed matrix (i.e., is a specialization of Matrix, Mean, or EuclideanMean)...
Definition: object-types.hpp:110
The root namespace for OpenKalman.
Definition: basics.hpp:34
auto split_diagonal(M &&m)
Split Covariance or SquareRootCovariance diagonally.
Definition: covariance-overloads.hpp:326
constexpr auto solve(A &&a, B &&b)
Solve the equation AX = B for X, which may or may not be a unique solution.
Definition: solve.hpp:87
constexpr auto determinant(Arg &&arg)
Take the determinant of a matrix.
Definition: determinant.hpp:44
Scalar entropy() const
Entropy of the distribution, in bits.
Definition: GaussianDistribution.hpp:358
GaussianDistribution(M &&mean, Cov &&cov)
Construct from matrices representing a mean and a covariance.
Definition: GaussianDistribution.hpp:170
typename vector_space_descriptor_of< T, N >::type vector_space_descriptor_of_t
helper template for vector_space_descriptor_of.
Definition: vector_space_descriptor_of.hpp:56
constexpr bool covariance
T is a specialization of either Covariance or SquareRootCovariance.
Definition: object-types.hpp:161
Layout
The layout format of a multidimensional array.
Definition: global-definitions.hpp:47
GaussianDistribution(Arg &&arg)
Construct from related distribution.
Definition: GaussianDistribution.hpp:100
decltype(auto) constexpr sum(Ts &&...ts)
Element-by-element sum of one or more objects.
Definition: sum.hpp:112
Mean mu
The mean of the distribution.
Definition: GaussianDistribution.hpp:368
A generalization of std::less_equal in which the arguments may be of different types.
Definition: less_equal.hpp:29
GaussianDistribution(Mean &&mean, Covariance &&cov)
Construct from an rvalue of a mean and a covariance.
Definition: GaussianDistribution.hpp:107
auto make_covariance(Arg &&arg)
Make a Covariance from a covariance_nestable, specifying the fixed_pattern.
Definition: Covariance.hpp:735
constexpr bool gaussian_distribution
T is a Gaussian distribution.
Definition: object-types.hpp:182
The dimension of an index for a matrix, expression, or array.
Definition: index_dimension_of.hpp:34
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.
GaussianDistribution & operator=(Arg &&arg)
Assign from another compatible distribution.
Definition: GaussianDistribution.hpp:262
constexpr bool fixed_pattern
A coordinates::pattern for which the size is fixed at compile time.
Definition: fixed_pattern.hpp:47
auto operator()() const
Generate a random value from the distribution.
Definition: GaussianDistribution.hpp:325
constexpr std::size_t dynamic_size
A constant indicating that a size or index is dynamic.
Definition: global-definitions.hpp:33
constexpr bool mean
Specifies that T is a mean (i.e., is a specialization of the class Mean).
Definition: object-types.hpp:40
constexpr bool covariance_nestable
T is an acceptable nested matrix for a covariance (including triangular_covariance).
Definition: object-types.hpp:237
auto split_vertical(M &&m)
Split Covariance or SquareRootCovariance vertically. Result is a tuple of typed matrices.
Definition: covariance-overloads.hpp:340
auto inverse_scale(M &&m, const S s)
Scale a covariance by the inverse of a scalar factor.
Definition: covariance-arithmetic.hpp:543
auto scale(M &&m, const S s)
Scale a covariance by a factor.
Definition: covariance-arithmetic.hpp:518
decltype(auto) constexpr nested_object(Arg &&arg)
Retrieve a nested object of Arg, if it exists.
Definition: nested_object.hpp:34
auto split(D &&d)
Split distribution.
Definition: GaussianDistribution.hpp:918
GaussianDistribution(Cov &&cov)
Construct with only a covariance or square typed_matrix (mean is set to zero).
Definition: GaussianDistribution.hpp:234
GaussianDistribution(M &&mean, Covariance &&cov)
Construct from a typed_matrix and an rvalue of a covariance.
Definition: GaussianDistribution.hpp:120
Scalar log_likelihood(const Z &...z) const
Log-likelihood function for a set of i.i.d.
Definition: GaussianDistribution.hpp:348
decltype(auto) constexpr trace(Arg &&arg)
Take the trace of a matrix.
Definition: trace.hpp:35
A matrix with typed rows and columns.
Definition: forward-class-declarations.hpp:448
constexpr auto get_vector_space_descriptor(const T &t, const N &n)
Get the coordinates::pattern object for index N of indexible object T.
Definition: get_vector_space_descriptor.hpp:56