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
33 (
std::is_same_v<scalar_type_of_t<MeanNestedMatrix>,
34 scalar_type_of_t<CovarianceNestedMatrix>>)
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);
50 static_assert(std::is_same_v<scalar_type_of_t<MeanNestedMatrix>,
51 scalar_type_of_t<CovarianceNestedMatrix>>);
56 static constexpr
auto dim = coordinates::dimension_of_v<StaticDescriptor>;
59 using Scalar = scalar_type_of_t<Mean>;
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<
bool Enable =
true, std::enable_if_t<Enable and
83 stdex::default_initializable<Mean> and stdex::default_initializable<Covariance>,
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
141 compares_with<vector_space_descriptor_of_t<Cov, 0>, StaticDescriptor>) or
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_pattern_collection<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_pattern_collection<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<stdex::convertible_to<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<stdex::convertible_to<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
343 ((vector<Z> and
compares_with<vector_space_descriptor_of_t<Z, 0>, StaticDescriptor>) and ...)
345 template<
typename...Z, std::enable_if_t<(
sizeof...(Z) > 0) and ((typed_matrix<Z> and vector<Z> and
346 compares_with<vector_space_descriptor_of_t<Z, 0>, StaticDescriptor>) and ...),
int> = 0>
350 static constexpr
auto n =
sizeof...(Z);
352 return -0.5 * (n * (dim *
values::log(2 * stdex::numbers::pi_v<long double>) +
360 return 0.5 * (dim * (1 + values::log2(stdex::numbers::pi_v<long double>) +
361 Scalar {stdex::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>
389 vector_space_descriptor_of_t<M, 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
408 coordinates::compares_with<vector_space_descriptor_of_t<C, 0>, vector_space_descriptor_of_t<C, 1>>
410 template<
typename M,
typename C, std::enable_if_t<
411 typed_matrix<M> and typed_matrix<C> and
412 compares_with<vector_space_descriptor_of_t<C, 0>, vector_space_descriptor_of_t<C, 1>>,
int> = 0>
415 vector_space_descriptor_of_t<M, 0>,
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>
437 vector_space_descriptor_of_t<C, 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>
462 vector_space_descriptor_of_t<C, 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
510 (
compares_with<vector_space_descriptor_of_t<M, 0>, vector_space_descriptor_of_t<Cov, 0>>)
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>)
578 using C = vector_space_descriptor_of_t<Cov, 0>;
579 using Covb = passable_t<nested_object_of_t<Cov>>;
582 else if constexpr(typed_matrix<Cov>)
584 using C = vector_space_descriptor_of_t<Cov, 0>;
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
645 coordinates::compares_with<vector_space_descriptor_of_t<M, 0>, vector_space_descriptor_of_t<Cov, 0>>
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
649 compares_with<vector_space_descriptor_of_t<M, 0>, vector_space_descriptor_of_t<Cov, 0>>,
int> = 0>
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>
732 static const bool is_specialized =
true;
734 using scalar_type = scalar_type_of_t<NestedMean>;
736 template<
typename Arg>
737 static constexpr
auto count_indices(
const Arg& arg) {
return std::integral_constant<std::size_t, 1>{}; }
739 template<
typename Arg,
typename N>
742 if constexpr (values::fixed<N>)
744 static_assert(n == 0_uz);
745 if constexpr (not dynamic_dimension<NestedMean, 0>)
return OpenKalman::get_pattern_collection<0>(mean_of(arg));
746 else return OpenKalman::get_pattern_collection<0>(covariance_of(arg));
755 template<
typename Arg>
758 return std::forward<Arg>(arg).
mu;
762 #ifdef __cpp_lib_concepts 763 template<
typename Arg> requires raw_data_defined_for<Mean<Coeffs, NestedMean>>
765 template<
typename Arg, std::enable_if_t<raw_data_defined_for<Mean<Coeffs, NestedMean>>,
int> = 0>
767 static constexpr
auto *
768 raw_data(Arg& arg) {
return internal::raw_data(arg.mu()); }
771 static constexpr data_layout layout = layout_of_v<NestedMean>;
778 template<
typename Coeffs,
typename NestedMean,
typename NestedCovariance,
typename re>
781 using StaticDescriptor = Coeffs;
782 using Mean = Mean<StaticDescriptor, NestedMean>;
783 using Covariance = Covariance<StaticDescriptor, NestedCovariance>;
784 using Scalar = scalar_type_of_t<Mean>;
785 template<
typename S>
using distribution_type = std::normal_distribution<S>;
786 using random_number_engine = re;
788 #ifdef __cpp_concepts 789 template<fixed_pattern C = StaticDescriptor, typed_matrix_nestable M, covariance_nestable Cov> requires
790 vector<M> and (index_dimension_of_v<M, 0> == index_dimension_of_v<Cov, 0>)
792 template<
typename C = StaticDescriptor,
typename M,
typename Cov,
793 std::enable_if_t<fixed_pattern<C> and typed_matrix_nestable<M> and covariance_nestable<Cov> and
798 return make_GaussianDistribution<C, random_number_engine>(std::forward<M>(
mean), std::forward<Cov>(
covariance));
808 #ifdef __cpp_concepts 809 template<gaussian_distribution Arg>
811 template<
typename Arg, std::enable_if_t<gaussian_distribution<Arg>,
int> = 0>
813 constexpr decltype(
auto)
816 return (std::forward<Arg>(arg).
mu);
820 #ifdef __cpp_concepts 821 template<gaussian_distribution Arg>
823 template<
typename Arg, std::enable_if_t<gaussian_distribution<Arg>,
int> = 0>
825 constexpr decltype(
auto)
826 covariance_of(Arg&& arg)
828 return (std::forward<Arg>(arg).
sigma);
832 #ifdef __cpp_concepts 833 template<gaussian_distribution T, std::
size_t dimension = index_dimension_of_v<T, 0>,
834 typename Scalar = scalar_type_of_t<T>, std::convertible_to<std::
size_t>...runtime_dimensions> requires
835 (
sizeof...(runtime_dimensions) == (dimension == stdex::dynamic_extent ? 1 : 0))
838 typename Scalar =
typename scalar_type_of<T>::type,
typename...runtime_dimensions, std::enable_if_t<
839 gaussian_distribution<T> and (
sizeof...(runtime_dimensions) == (dimension == stdex::dynamic_extent ? 1 : 0)) and
840 (stdex::convertible_to<runtime_dimensions, std::size_t> and ...),
int> = 0>
843 make_zero_distribution_like(runtime_dimensions...e)
845 using Coeffs =
typename DistributionTraits<T>::StaticDescriptor;
846 using re = DistributionTraits<T>::random_number_engine;
849 return make_gaussian_distribution<re>>(std::move(m), std::move(c));
853 #ifdef __cpp_concepts 854 template<gaussian_distribution T, std::
size_t dimension = index_dimension_of_v<T, 0>,
855 typename Scalar = scalar_type_of_t<T>, std::convertible_to<std::
size_t>...runtime_dimensions> requires
856 (
sizeof...(runtime_dimensions) == (dimension == stdex::dynamic_extent ? 1 : 0))
858 template<typename T, std::size_t dimension = index_dimension_of<T, 0>::value,
859 typename Scalar =
typename scalar_type_of<T>::type,
typename...runtime_dimensions, std::enable_if_t<
860 gaussian_distribution<T> and (
sizeof...(runtime_dimensions) == (dimension == stdex::dynamic_extent ? 1 : 0)) and
861 (stdex::convertible_to<runtime_dimensions, std::size_t> and ...),
int> = 0>
864 make_normal_distribution_like(runtime_dimensions...e)
866 using Coeffs =
typename DistributionTraits<T>::StaticDescriptor;
867 using re = DistributionTraits<T>::random_number_engine;
870 return make_gaussian_distribution<re>>(std::move(m), std::move(c));
874 #ifdef __cpp_concepts 877 template<
typename D,
typename ... Ds,
878 std::enable_if_t<(gaussian_distribution<D> and ... and gaussian_distribution<Ds>),
int> = 0>
881 concatenate(D&& d, Ds&& ... ds)
883 if constexpr(
sizeof...(Ds) > 0)
885 using re =
typename DistributionTraits<D>::random_number_engine;
886 auto m = concatenate(mean_of(std::forward<D>(d)), mean_of(std::forward<Ds>(ds))...);
887 auto cov = concatenate(covariance_of(std::forward<D>(d)), covariance_of(std::forward<Ds>(ds))...);
888 return make_GaussianDistribution<re>(std::move(m), std::move(cov));
899 template<
typename Dist,
typename Means,
typename Covariances, std::size_t ... ints>
902 using re =
typename DistributionTraits<Dist>::random_number_engine;
903 return std::tuple {make_GaussianDistribution<re>(
904 std::get<ints>(std::forward<Means>(ms)),
905 std::get<ints>(std::forward<Covariances>(cs)))...};
911 #ifdef __cpp_concepts 915 template<
typename ... Cs,
typename D, std::enable_if_t<
916 (fixed_pattern<Cs> and ...) and gaussian_distribution<D> and
917 coordinates::compares_with<static_concatenate_t<Cs...>,
typename DistributionTraits<D>::StaticDescriptor, less_equal<>>,
int> = 0>
922 using Coeffs =
typename DistributionTraits<D>::StaticDescriptor;
923 if constexpr(
sizeof...(Cs) == 1 and
compares_with<static_concatenate_t<Cs...>, Coeffs>)
925 return std::tuple(std::forward<D>(d));
930 auto covariances =
split_diagonal<Cs...>(covariance_of(std::forward<D>(d)));
931 return OpenKalman::detail::zip_dist<D>(means, covariances, std::index_sequence_for<Cs...> {});
936 #ifdef __cpp_concepts 937 template<gaussian_distribution Dist>
939 template<
typename Dist, std::enable_if_t<gaussian_distribution<Dist>,
int> = 0>
942 operator<<(std::ostream& os,
const Dist& d)
944 os <<
"mean:" << std::endl << mean_of(d) << std::endl <<
945 "covariance:" << std::endl << covariance_of(d) << std::endl;
954 #ifdef __cpp_concepts 955 template<gaussian_distribution Dist1, gaussian_distribution Dist2> requires
956 coordinates::compares_with<typename DistributionTraits<Dist1>::StaticDescriptor,
typename DistributionTraits<Dist2>::StaticDescriptor>
958 template<
typename Dist1,
typename Dist2, std::enable_if_t<
959 gaussian_distribution<Dist1> and gaussian_distribution<Dist2> and
960 coordinates::compares_with<typename DistributionTraits<Dist1>::StaticDescriptor,
961 typename DistributionTraits<Dist2>::StaticDescriptor>,
int> = 0>
964 operator+(Dist1&& d1, Dist2&& d2)
966 using re =
typename DistributionTraits<Dist1>::random_number_engine;
967 auto m1 = mean_of(std::forward<Dist1>(d1)) + mean_of(std::forward<Dist2>(d2));
968 auto m2 = covariance_of(std::forward<Dist1>(d1)) + covariance_of(std::forward<Dist2>(d2));
969 return make_GaussianDistribution<re>(std::move(m1), std::move(m2));
973 #ifdef __cpp_concepts 974 template<gaussian_distribution Dist1, gaussian_distribution Dist2> requires
975 coordinates::compares_with<typename DistributionTraits<Dist1>::StaticDescriptor,
typename DistributionTraits<Dist2>::StaticDescriptor>
977 template<
typename Dist1,
typename Dist2, std::enable_if_t<
978 gaussian_distribution<Dist1> and gaussian_distribution<Dist2> and
979 coordinates::compares_with<typename DistributionTraits<Dist1>::StaticDescriptor,
980 typename DistributionTraits<Dist2>::StaticDescriptor>,
int> = 0>
983 operator-(Dist1&& d1, Dist2&& d2)
985 using re =
typename DistributionTraits<Dist1>::random_number_engine;
986 auto m1 = mean_of(std::forward<Dist1>(d1)) - mean_of(std::forward<Dist2>(d2));
987 auto m2 = covariance_of(std::forward<Dist1>(d1)) - covariance_of(std::forward<Dist2>(d2));
988 return make_GaussianDistribution<re>(std::move(m1), std::move(m2));
992 #ifdef __cpp_concepts 993 template<typed_matrix A, gaussian_distribution D> requires gaussian_distribution<D> and
994 (not euclidean_transformed<A>) and
995 (
compares_with<vector_space_descriptor_of_t<A, 1>,
typename DistributionTraits<D>::StaticDescriptor>)
997 template<
typename A,
typename D, std::enable_if_t<typed_matrix<A> and gaussian_distribution<D> and
998 (not eucl
idean_transformed<A>) and
999 (compares_with<vector_space_descriptor_of_t<A, 1>,
typename DistributionTraits<D>::StaticDescriptor>),
int> = 0>
1002 operator*(A&& a, D&& d)
1004 using re =
typename DistributionTraits<D>::random_number_engine;
1005 auto m = a * mean_of(std::forward<D>(d));
1006 auto c =
scale(covariance_of(std::forward<D>(d)), std::forward<A>(a));
1007 return make_GaussianDistribution<re>(std::move(m), std::move(c));
1011 #ifdef __cpp_concepts 1012 template<gaussian_distribution Dist, std::convertible_to<const typename DistributionTraits<Dist>::Scalar> S>
1014 template<
typename Dist,
typename S, std::enable_if_t<
1015 gaussian_distribution<Dist> and stdex::convertible_to<S, const typename DistributionTraits<Dist>::Scalar>,
int> = 0>
1018 operator*(Dist&& d, S s)
1020 using re =
typename DistributionTraits<Dist>::random_number_engine;
1021 auto m = mean_of(std::forward<Dist>(d)) * s;
1022 auto c =
scale(covariance_of(std::forward<Dist>(d)), s);
1023 return make_GaussianDistribution<re>(std::move(m), std::move(c));
1027 #ifdef __cpp_concepts 1028 template<gaussian_distribution Dist, std::convertible_to<const typename DistributionTraits<Dist>::Scalar> S>
1030 template<
typename Dist,
typename S, std::enable_if_t<
1031 gaussian_distribution<Dist> and stdex::convertible_to<S, const typename DistributionTraits<Dist>::Scalar>,
int> = 0>
1034 operator*(S s, Dist&& d)
1036 using re =
typename DistributionTraits<Dist>::random_number_engine;
1037 auto m = s * mean_of(std::forward<Dist>(d));
1038 auto c =
scale(covariance_of(std::forward<Dist>(d)), s);
1039 return make_GaussianDistribution<re>(std::move(m), std::move(c));
1043 #ifdef __cpp_concepts 1044 template<gaussian_distribution Dist, std::convertible_to<const typename DistributionTraits<Dist>::Scalar> S>
1046 template<
typename Dist,
typename S, std::enable_if_t<
1047 gaussian_distribution<Dist> and std::is_convertible_v<S, const typename DistributionTraits<Dist>::Scalar>,
int> = 0>
1050 operator/(Dist&& d, S s)
1052 using re =
typename DistributionTraits<Dist>::random_number_engine;
1053 auto m = mean_of(std::forward<Dist>(d)) / s;
1054 auto c =
inverse_scale(covariance_of(std::forward<Dist>(d)), s);
1055 return make_GaussianDistribution<re>(std::move(m), std::move(c));
typename nested_object_of< T >::type nested_object_of_t
Helper type for nested_object_of.
Definition: nested_object_of.hpp:58
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
GaussianDistribution(Mean &&mean, Cov &&cov)
Construct from an rvalue of a mean and a covariance, typed_matrix, or covariance_nestable.
Definition: GaussianDistribution.hpp:146
auto make_GaussianDistribution(D &&dist)
Make a Gaussian distribution.
Definition: GaussianDistribution.hpp:494
constexpr auto count_indices(const T &)
Get the number of indices necessary to address all the components of an indexible object...
Definition: count_indices.hpp:51
decltype(auto) constexpr get_pattern_collection(T &&t)
Get the coordinates::pattern_collection associated with indexible object T.
Definition: get_pattern_collection.hpp:59
constexpr bool value
T is a fixed or dynamic value that is reducible to a number.
Definition: value.hpp:45
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. ...
constexpr bool triangular_matrix
Specifies that an argument is an indexible object having a given triangle_type (e.g., upper, lower, or diagonal).
Definition: triangular_matrix.hpp:36
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
Definition: object_traits.hpp:38
constexpr bool fixed_pattern
A coordinates::pattern for which the dimension is fixed at compile time.
Definition: fixed_pattern.hpp:46
auto split_diagonal(M &&m)
Split Covariance or SquareRootCovariance diagonally.
Definition: covariance-overloads.hpp:326
decltype(auto) constexpr transpose(Arg &&arg)
Swap any two indices of an indexible_object.
Definition: transpose.hpp:163
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
constexpr bool covariance
T is a specialization of either Covariance or SquareRootCovariance.
Definition: object-types.hpp:161
An upper-right triangular matrix.
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
Definition: trait_backports.hpp:64
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:35
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
auto operator()() const
Generate a random value from the distribution.
Definition: GaussianDistribution.hpp:325
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:35
auto split(D &&d)
Split distribution.
Definition: GaussianDistribution.hpp:920
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
constexpr bool compares_with
Compares two coordinates::pattern objects.
Definition: compares_with.hpp:475
A matrix with typed rows and columns.
Definition: forward-class-declarations.hpp:292