1#ifndef QUICKSTATS_MEDIAN_HPP
2#define QUICKSTATS_MEDIAN_HPP
22template<
typename Output_ =
double>
46template<
typename Output_ =
double,
typename Input_>
48 static_assert(std::is_floating_point<Output_>::value);
54 const std::size_t halfway = num_total / 2;
55 const bool is_even = (num_total % 2 == 0);
57 std::nth_element(ptr, ptr + halfway, ptr + num_total);
58 const Output_ medtmp = *(ptr + halfway);
68 const Output_ other = *std::max_element(ptr, ptr + halfway);
70 return interpolate<Output_>(medtmp, other, 0.5);
77template<
typename Output_,
typename Input_>
78Output_ median_internal(
const std::size_t num_total,
const std::size_t num_non_zero, Input_*
const non_zero_values,
const Input_ zero_value,
const MedianOptions<Output_>& options) {
79 assert(num_total >= num_non_zero);
84 if (num_non_zero == num_total) {
91 if (num_non_zero < num_total - num_non_zero) {
95 const std::size_t halfway = num_total / 2;
96 const bool is_even = (num_total % 2 == 0);
98 const std::size_t num_zero = num_total - num_non_zero;
99 std::size_t num_below = 0;
100 for (std::size_t i = 0; i < num_non_zero; ++i) {
101 num_below += (non_zero_values[i] < zero_value);
105 if (num_below > halfway) {
106 std::nth_element(non_zero_values, non_zero_values + halfway, non_zero_values + num_non_zero);
107 return non_zero_values[halfway];
109 }
else if (halfway >= num_below + num_zero) {
110 const std::size_t skip_zeros = halfway - num_zero;
111 std::nth_element(non_zero_values, non_zero_values + skip_zeros, non_zero_values + num_non_zero);
112 return non_zero_values[skip_zeros];
119 Output_ baseline = zero_value, other = zero_value;
120 if (num_below > halfway) {
121 std::nth_element(non_zero_values, non_zero_values + halfway, non_zero_values + num_non_zero);
122 baseline = non_zero_values[halfway];
123 other = *(std::max_element(non_zero_values, non_zero_values + halfway));
125 }
else if (num_below == halfway) {
126 const std::size_t below_halfway = halfway - 1;
127 std::nth_element(non_zero_values, non_zero_values + below_halfway, non_zero_values + num_non_zero);
128 other = non_zero_values[below_halfway];
130 }
else if (num_below < halfway && num_below + num_zero > halfway) {
133 }
else if (num_below + num_zero == halfway) {
134 const std::size_t skip_zeros = halfway - num_zero;
135 std::nth_element(non_zero_values, non_zero_values + skip_zeros, non_zero_values + num_non_zero);
136 other = non_zero_values[skip_zeros];
139 const std::size_t skip_zeros = halfway - num_zero;
140 std::nth_element(non_zero_values, non_zero_values + skip_zeros, non_zero_values + num_non_zero);
141 baseline = non_zero_values[skip_zeros];
142 other = *(std::max_element(non_zero_values, non_zero_values + skip_zeros));
145 return interpolate<Output_>(baseline, other, 0.5);
171template<
typename Output_ =
double,
typename Input_>
173 return median_internal<Output_>(num_total, num_non_zero, values,
static_cast<Input_
>(0), options);
180template<
typename Output_ =
double,
typename Input_>
181Output_
median(
const std::size_t num_total, Input_*
const ptr) {
182 return median(num_total, ptr, MedianOptions<Output_>());
185template<
typename Output_ =
double,
typename Input_>
186Output_
median(
const std::size_t num_total,
const std::size_t num_non_zero, Input_*
const values) {
187 return median(num_total, num_non_zero, values, MedianOptions<Output_>());
Quickly compute simple statistics.
Definition mad.hpp:15
Output_ median(const std::size_t num_total, Input_ *const ptr, const MedianOptions< Output_ > &options)
Definition median.hpp:47
constexpr Value_ nan_if_available_else_zero()
Definition utils.hpp:63