RandLib 2.0.0
Probability distributions, fitting, and heavy-tail tools for C++20
Loading...
Searching...
No Matches
select.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <randlib/fit/mle.hpp>
4
5#include <cmath>
6#include <concepts>
7#include <limits>
8#include <optional>
9#include <ranges>
10#include <span>
11#include <type_traits>
12#include <utility>
13#include <variant>
14
15namespace randlib
16{
17
18template <class... Distributions>
20{
21 std::variant<FitResult<Distributions>...> fit;
22 std::size_t index = 0;
24 double value = std::numeric_limits<double>::infinity();
25};
26
27template <class First, class... Rest>
29 (std::same_as<typename First::value_type, typename Rest::value_type> && ...)
30BestFitResult<First, Rest...> fit_best(std::span<const typename First::value_type> sample, Criterion criterion)
31{
32 using Result = BestFitResult<First, Rest...>;
33 using Variant = decltype(Result::fit);
34 std::optional<Variant> best;
35 double bestValue = std::numeric_limits<double>::infinity();
36 std::size_t bestIndex = 0;
37 std::size_t index = 0;
38 auto consider = [&]<class Distribution>() {
39 try {
40 auto candidate = fit<Distribution>(sample);
41 const double value = criterion == Criterion::AIC ? candidate.aic : candidate.bic;
42 if (candidate.converged && std::isfinite(value) && value < bestValue) {
43 best.emplace(std::move(candidate));
44 bestValue = value;
45 bestIndex = index;
46 }
47 } catch (const std::exception &) {
48 }
49 ++index;
50 };
51 consider.template operator()<First>();
52 (consider.template operator()<Rest>(), ...);
53 if (!best)
54 throw fit_error(FitErrorCode::Undefined, "No candidate distribution produced a finite converged fit");
55 return {std::move(*best), bestIndex, criterion, bestValue};
56}
57
58template <class First, class... Rest, std::ranges::contiguous_range Range>
59 requires std::same_as<std::remove_cv_t<std::ranges::range_value_t<Range>>, typename First::value_type> &&
61 (std::same_as<typename First::value_type, typename Rest::value_type> && ...)
62BestFitResult<First, Rest...> fit_best(const Range &sample, Criterion criterion)
63{
64 return fit_best<First, Rest...>(std::span<const typename First::value_type>(sample), criterion);
65}
66
67} // namespace randlib
The fit_error class Thrown when a distribution cannot be fitted to a sample; code() tells why.
Definition errors.hpp:36
Definition mle.hpp:91
Real standardNormal(G &g)
Ziggurat algorithm of Marsaglia and Tsang with 256 layers and an explicit sign bit.
Definition variates.hpp:45
Definition bivariate_normal.hpp:10
@ Undefined
any other failure
BestFitResult< First, Rest... > fit_best(std::span< const typename First::value_type > sample, Criterion criterion)
Definition select.hpp:30
Criterion
Definition result.hpp:21
Definition select.hpp:20
std::variant< FitResult< Distributions >... > fit
Definition select.hpp:21
Criterion criterion
Definition select.hpp:23
std::size_t index
Definition select.hpp:22
double value
Definition select.hpp:24