Automatic Differentiation
 
Loading...
Searching...
No Matches
quantile.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_PRIM_FUN_QUANTILE_HPP
2#define STAN_MATH_PRIM_FUN_QUANTILE_HPP
3
8#include <algorithm>
9
10namespace stan {
11namespace math {
12
29template <typename T, require_vector_t<T>* = nullptr,
30 require_vector_vt<std::is_arithmetic, T>* = nullptr>
31inline double quantile(const T& samples_vec, const double p) {
32 check_not_nan("quantile", "p", p);
33 check_bounded("quantile", "p", p, 0, 1);
34
35 const size_t n_sample = samples_vec.size();
36 if (n_sample == 0) {
37 return {};
38 }
39
40 Eigen::VectorXd x = as_array_or_scalar(samples_vec);
41 check_not_nan("quantile", "samples_vec", x);
42
43 if (n_sample == 1) {
44 return x.coeff(0);
45 } else if (p == 0.) {
46 return x.minCoeff();
47 } else if (p == 1.) {
48 return x.maxCoeff();
49 }
50
51 const size_t nm1 = (n_sample - 1);
52 const double index = nm1 * p;
53 const size_t lo = static_cast<size_t>(index);
54
55 std::nth_element(x.data(), x.data() + lo, x.data() + n_sample);
56
57 const double h = index - lo;
58 if (h == 0) {
59 return x.coeff(lo);
60 }
61 return (1 - h) * x.coeff(lo) + h * x.tail(nm1 - lo).minCoeff();
62}
63
81template <typename T, typename Tp,
82 typename ReturnT = promote_scalar_t<double, Tp>,
86inline ReturnT quantile(const T& samples_vec, const Tp& ps) {
87 check_not_nan("quantile", "ps", ps);
88 check_bounded("quantile", "ps", ps, 0, 1);
89
90 const size_t n_sample = samples_vec.size();
91 const size_t n_ps = ps.size();
92 if (n_ps == 0 || n_sample == 0) {
93 return {};
94 }
95
96 plain_type_t<T> x = samples_vec;
97 check_not_nan("quantile", "samples_vec", x);
98
99 std::sort(x.begin(), x.end());
100 ReturnT ret(n_ps);
101
102 const size_t nm1 = (n_sample - 1);
103
104 for (size_t i = 0; i < n_ps; i++) {
105 const double sample_xi = nm1 * ps[i];
106 const size_t smpl_xi_int = static_cast<size_t>(sample_xi);
107 const double smpl_xi_frc = sample_xi - smpl_xi_int;
108 ret[i] = (1 - smpl_xi_frc) * x[smpl_xi_int];
109 if (smpl_xi_frc != 0.0) {
110 ret[i] += smpl_xi_frc * x[smpl_xi_int + 1];
111 }
112 }
113
114 return ret;
115}
116
117} // namespace math
118} // namespace stan
119
120#endif
require_t< container_type_check_base< is_vector, value_type_t, TypeCheck, Check... > > require_vector_vt
Require type satisfies is_vector.
require_all_t< is_vector< std::decay_t< Types > >... > require_all_vector_t
Require all of the types satisfy is_vector.
T as_array_or_scalar(T &&v)
Returns specified input value.
void check_bounded(const char *function, const char *name, const T_y &y, const T_low &low, const T_high &high)
Check if the value is between the low and high values, inclusively.
double quantile(const T &samples_vec, const double p)
Return sample quantiles corresponding to the given probabilities.
Definition quantile.hpp:31
void check_not_nan(const char *function, const char *name, const T_y &y)
Check if y is not NaN.
typename plain_type< std::decay_t< T > >::type plain_type_t
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...