Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
stat_utils.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
94#ifndef STAT_UTILS_H
95#define STAT_UTILS_H
96
97#include "ahSort.H"
98#include "tpl_dynMapTree.H"
99
100#include <cmath>
101#include <limits>
102#include <algorithm>
103#include <vector>
104#include <stdexcept>
105#include <ah-errors.H>
106#include <tpl_sort_utils.H>
107#include <tpl_dynArray.H>
108
109namespace Aleph {
110
111// =============================================================================
112// Stats Result Structure
113// =============================================================================
114
123template <typename T>
124struct Stats
125{
126 size_t count = 0;
127 T sum = T();
128 T mean = T();
130 T stddev = T();
131 T median = T();
132 T min = T();
133 T max = T();
134 T q1 = T();
135 T q3 = T();
136 T iqr = T();
140
146 {
147 return count > 0;
148 }
149
155 {
156 return max - min;
157 }
158};
159
160// =============================================================================
161// Basic Statistical Functions
162// =============================================================================
163
171template <typename Container>
172[[nodiscard]] auto sum(const Container &data) -> std::decay_t<decltype(*std::begin(data))>
173{
174 using T = std::decay_t<decltype(*std::begin(data))>;
175 T result = T();
176 for (const auto &x : data)
177 result += x;
178 return result;
179}
180
189template <typename Container>
190[[nodiscard]] auto mean(const Container &data) -> std::decay_t<decltype(*std::begin(data))>
191{
192 using T = std::decay_t<decltype(*std::begin(data))>;
193 size_t n = 0;
194 T s = T();
195 for (const auto &x : data)
196 {
197 s += x;
198 ++n;
199 }
200 ah_invalid_argument_if(n == 0) << "mean: empty container";
201 return s / static_cast<T>(n);
202}
203
219template <typename Container>
220[[nodiscard]] auto variance(const Container &data,
221 bool population = false) -> std::decay_t<decltype(*std::begin(data))>
222{
223 using T = std::decay_t<decltype(*std::begin(data))>;
224
225 size_t n = 0;
226 T m = T(); // Running mean
227 T m2 = T(); // Sum of squared differences from mean
228
229 // Welford's online algorithm
230 for (const auto &x : data)
231 {
232 ++n;
233 T delta = x - m;
234 m += delta / static_cast<T>(n);
235 T delta2 = x - m;
236 m2 += delta * delta2;
237 }
238
239 if (population)
240 {
241 ah_invalid_argument_if(n == 0) << "variance: empty container";
242 return m2 / static_cast<T>(n);
243 }
244 ah_invalid_argument_if(n < 2) << "variance: need at least 2 elements for sample variance";
245 return m2 / static_cast<T>(n - 1);
246}
247
256template <typename Container>
257[[nodiscard]] auto stddev(const Container &data,
258 bool population = false) -> std::decay_t<decltype(*std::begin(data))>
259{
260 return std::sqrt(variance(data, population));
261}
262
271template <typename Container>
272[[nodiscard]] auto min_value(const Container &data) -> std::decay_t<decltype(*std::begin(data))>
273{
274 auto it = std::begin(data);
275 auto end = std::end(data);
276 ah_invalid_argument_if(it == end) << "min_value: empty container";
277
278 auto result = *it;
279 for (++it; it != end; ++it)
280 if (*it < result)
281 result = *it;
282 return result;
283}
284
293template <typename Container>
294[[nodiscard]] auto max_value(const Container &data) -> std::decay_t<decltype(*std::begin(data))>
295{
296 auto it = std::begin(data);
297 auto end = std::end(data);
298 ah_invalid_argument_if(it == end) << "max_value: empty container";
299
300 auto result = *it;
301 for (++it; it != end; ++it)
302 if (*it > result)
303 result = *it;
304 return result;
305}
306
315template <typename Container>
316[[nodiscard]] auto min_max(const Container &data)
317 -> std::pair<std::decay_t<decltype(*std::begin(data))>, std::decay_t<decltype(*std::begin(data))>>
318{
319 using T = std::decay_t<decltype(*std::begin(data))>;
320 auto it = std::begin(data);
321 auto end = std::end(data);
322 ah_invalid_argument_if(it == end) << "min_max: empty container";
323
324 T min_val = *it;
325 T max_val = *it;
326 for (++it; it != end; ++it)
327 {
328 if (*it < min_val)
329 min_val = *it;
330 if (*it > max_val)
331 max_val = *it;
332 }
333 return {min_val, max_val};
334}
335
336// =============================================================================
337// Percentile and Median Functions
338// =============================================================================
339
351template <typename Container>
352[[nodiscard]] auto percentile(const Container &data,
353 double p) -> std::decay_t<decltype(*std::begin(data))>
354{
355 using T = std::decay_t<decltype(*std::begin(data))>;
356
357 ah_invalid_argument_if(p < 0 or p > 100) << "percentile: p must be in [0, 100]";
358
360 for (const auto &x : data)
361 sorted.append(x);
362 ah_invalid_argument_if(sorted.is_empty()) << "percentile: empty container";
363
365
366 if (p == 0)
367 return sorted[0];
368 if (p == 100)
369 return sorted[sorted.size() - 1];
370
371 // Calculate index
372 const double index = (p / 100.0) * (sorted.size() - 1);
373 auto lower = static_cast<size_t>(std::floor(index));
374 auto upper = static_cast<size_t>(std::ceil(index));
375
376 if (lower == upper)
377 return sorted[lower];
378
379 // Linear interpolation
380 double fraction = index - lower;
381 return static_cast<T>(sorted[lower] * (1 - fraction) + sorted[upper] * fraction);
382}
383
392template <typename Container>
393[[nodiscard]] auto median(const Container &data) -> std::decay_t<decltype(*std::begin(data))>
394{
395 return percentile(data, 50);
396}
397
405template <typename Container>
406[[nodiscard]] auto quartiles(const Container &data)
407 -> std::tuple<std::decay_t<decltype(*std::begin(data))>,
408 std::decay_t<decltype(*std::begin(data))>,
409 std::decay_t<decltype(*std::begin(data))>>
410{
411 using T = std::decay_t<decltype(*std::begin(data))>;
412 T q1 = percentile(data, 25);
413 T q2 = percentile(data, 50);
414 T q3 = percentile(data, 75);
415 return {q1, q2, q3};
416}
417
425template <typename Container>
426[[nodiscard]] auto iqr(const Container &data) -> std::decay_t<decltype(*std::begin(data))>
427{
428 return percentile(data, 75) - percentile(data, 25);
429}
430
431// =============================================================================
432// Mode
433// =============================================================================
434
446template <typename Container>
447[[nodiscard]] auto mode(const Container &data) -> std::decay_t<decltype(*std::begin(data))>
448{
449 using T = std::decay_t<decltype(*std::begin(data))>;
450 auto it = std::begin(data);
451 auto end = std::end(data);
452 ah_invalid_argument_if(it == end) << "mode: empty container";
453
455
456 for (const auto &x : data)
457 ++freq[x];
458
459 T mode_val = freq.begin()->first;
460 size_t max_count = freq.begin()->second;
461
462 for (const auto &[val, count] : freq)
463 if (count > max_count)
464 {
466 mode_val = val;
467 }
468
469 return mode_val;
470}
471
479template <typename Container>
480[[nodiscard]] bool is_multimodal(const Container &data)
481{
482 using T = std::decay_t<decltype(*std::begin(data))>;
483
485 for (const auto &x : data)
486 ++freq[x];
487
488 if (freq.is_empty())
489 return false;
490
491 size_t max_count = 0;
492 for (const auto &[val, count] : freq)
493 if (count > max_count)
495
496 size_t modes = 0;
497 for (const auto &[val, count] : freq)
498 if (count == max_count)
499 ++modes;
500
501 return modes > 1;
502}
503
504// =============================================================================
505// Higher Moments
506// =============================================================================
507
522template <typename Container>
523[[nodiscard]] auto skewness(const Container &data) -> std::decay_t<decltype(*std::begin(data))>
524{
525 using T = std::decay_t<decltype(*std::begin(data))>;
526
527 T m = mean(data);
528 T s = stddev(data);
529
530 if (s == T())
531 return T(); // All values are equal
532
533 size_t n = 0;
534 T sum3 = T();
535 for (const auto &x : data)
536 {
537 T diff = (x - m) / s;
538 sum3 += diff * diff * diff;
539 ++n;
540 }
541
542 ah_invalid_argument_if(n < 3) << "skewness: need at least 3 elements";
543
544 // Adjusted Fisher-Pearson coefficient
545 T factor = static_cast<T>(n) / ((n - 1) * (n - 2));
546 return factor * sum3;
547}
548
563template <typename Container>
564[[nodiscard]] auto kurtosis(const Container &data) -> std::decay_t<decltype(*std::begin(data))>
565{
566 using T = std::decay_t<decltype(*std::begin(data))>;
567
568 T m = mean(data);
569 T s = stddev(data);
570
571 if (s == T())
572 return T(); // All values are equal
573
574 size_t n = 0;
575 T sum4 = T();
576 for (const auto &x : data)
577 {
578 T diff = (x - m) / s;
579 T diff2 = diff * diff;
580 sum4 += diff2 * diff2;
581 ++n;
582 }
583
584 ah_invalid_argument_if(n < 4) << "kurtosis: need at least 4 elements";
585
586 // Excess kurtosis with bias correction
587 T n_t = static_cast<T>(n);
588 T factor1 = (n_t * (n_t + 1)) / ((n_t - 1) * (n_t - 2) * (n_t - 3));
589 T factor2 = (3 * (n_t - 1) * (n_t - 1)) / ((n_t - 2) * (n_t - 3));
590
591 return factor1 * sum4 - factor2;
592}
593
604template <typename Container>
606 -> std::decay_t<decltype(*std::begin(data))>
607{
608 using T = std::decay_t<decltype(*std::begin(data))>;
609 T m = mean(data);
610 ah_invalid_argument_if(m == T()) << "coefficient_of_variation: mean is zero";
611 return stddev(data) / std::abs(m);
612}
613
614// =============================================================================
615// Correlation and Covariance
616// =============================================================================
617
629template <typename Container1, typename Container2>
631 const Container2 &y,
632 bool population = false) -> std::decay_t<decltype(*std::begin(x))>
633{
634 using T = std::decay_t<decltype(*std::begin(x))>;
635
636 auto it_x = std::begin(x);
637 auto it_y = std::begin(y);
638 auto end_x = std::end(x);
639 auto end_y = std::end(y);
640
641 // Welford-style online algorithm for covariance
642 size_t n = 0;
643 T mean_x = T();
644 T mean_y = T();
645 T c = T(); // Co-moment
646
647 while (it_x != end_x and it_y != end_y)
648 {
649 ++n;
650 T dx = *it_x - mean_x;
651 mean_x += dx / static_cast<T>(n);
652 T dy = *it_y - mean_y;
653 mean_y += dy / static_cast<T>(n);
654 c += dx * (*it_y - mean_y);
655
656 ++it_x;
657 ++it_y;
658 }
659
661 << "covariance: containers have different sizes";
662
663 if (population)
664 {
665 ah_invalid_argument_if(n == 0) << "covariance: empty containers";
666 return c / static_cast<T>(n);
667 }
668 ah_invalid_argument_if(n < 2) << "covariance: need at least 2 elements";
669 return c / static_cast<T>(n - 1);
670}
671
687template <typename Container1, typename Container2>
689 const Container2 &y) -> std::decay_t<decltype(*std::begin(x))>
690{
691 using T = std::decay_t<decltype(*std::begin(x))>;
692
693 T cov = covariance(x, y, true); // Use population covariance
694 T sx = stddev(x, true); // Population stddev
695 T sy = stddev(y, true);
696
697 ah_invalid_argument_if(sx == T() or sy == T())
698 << "correlation: one or both datasets have zero variance";
699
700 return cov / (sx * sy);
701}
702
703// =============================================================================
704// Histogram
705// =============================================================================
706
716template <typename Container>
717[[nodiscard]] auto histogram(const Container &data, size_t num_bins)
718 -> std::vector<std::pair<std::decay_t<decltype(*std::begin(data))>, size_t>>
719{
720 using T = std::decay_t<decltype(*std::begin(data))>;
721
722 ah_invalid_argument_if(num_bins == 0) << "histogram: num_bins must be > 0";
723
724 auto [min_val, max_val] = min_max(data);
725 T range = max_val - min_val;
726
727 if (range == T())
728 {
729 // All values are equal
730 return {{min_val, std::distance(std::begin(data), std::end(data))}};
731 }
732
733 T bin_width = range / static_cast<T>(num_bins);
734
735 std::vector<size_t> counts(num_bins, 0);
736
737 for (const auto &x : data)
738 {
739 auto bin = static_cast<size_t>((x - min_val) / bin_width);
740 if (bin >= num_bins)
741 bin = num_bins - 1; // Handle max value
742 ++counts[bin];
743 }
744
745 std::vector<std::pair<T, size_t>> result;
746 result.reserve(num_bins);
747
748 for (size_t i = 0; i < num_bins; ++i)
749 {
750 T center = min_val + (i + 0.5) * bin_width;
751 result.emplace_back(center, counts[i]);
752 }
753
754 return result;
755}
756
757// =============================================================================
758// Comprehensive Stats Function
759// =============================================================================
760
768template <typename Container>
770 -> Stats<std::decay_t<decltype(*std::begin(data))>>
771{
772 using T = std::decay_t<decltype(*std::begin(data))>;
773 Stats<T> s;
774
775 // Count elements
776 for (const auto &x : data)
777 {
778 s.sum += x;
779 ++s.count;
780 }
781
782 if (s.count == 0)
783 return s;
784
785 s.mean = s.sum / static_cast<T>(s.count);
786
787 // Min/Max
788 auto [min_val, max_val] = min_max(data);
789 s.min = min_val;
790 s.max = max_val;
791
792 // Variance and stddev (need at least 2 elements)
793 if (s.count >= 2)
794 {
795 s.variance = variance(data, false);
796 s.stddev = std::sqrt(s.variance);
797
798 // Coefficient of variation
799 if (s.mean != T())
800 s.coef_variation = s.stddev / std::abs(s.mean);
801 }
802
803 // Percentiles
804 s.median = percentile(data, 50);
805 s.q1 = percentile(data, 25);
806 s.q3 = percentile(data, 75);
807 s.iqr = s.q3 - s.q1;
808
809 // Higher moments (need at least 3/4 elements)
810 if (s.count >= 3)
811 s.skewness = skewness(data);
812
813 if (s.count >= 4)
814 s.kurtosis = kurtosis(data);
815
816 return s;
817}
818
819// =============================================================================
820// Legacy API (backward compatible)
821// =============================================================================
822
846template <class T>
847void compute_stats(T *data, int l, int r, T &avg, T &var, T &med, T &_min, T &_max)
848{
849 if (l > r)
850 {
851 avg = var = med = _min = _max = T();
852 return;
853 }
854
855 // Sort the array for quantiles
856 std::sort(data + l, data + r + 1);
857
858 _min = data[l];
859 _max = data[r];
860
861 // Calculate median (correctly using l offset)
862 int n = r - l + 1;
863 int mid = l + n / 2;
864 if (n % 2 == 0)
865 med = (data[mid - 1] + data[mid]) / 2;
866 else
867 med = data[mid];
868
869 // Welford's algorithm for mean and variance
870 T m = T();
871 T m2 = T();
872 for (int i = l; i <= r; ++i)
873 {
874 int k = i - l + 1;
875 T delta = data[i] - m;
876 m += delta / static_cast<T>(k);
877 T delta2 = data[i] - m;
878 m2 += delta * delta2;
879 }
880
881 avg = m;
882 var = (n > 1) ? m2 / static_cast<T>(n - 1) : T();
883}
884
898template <typename Container>
899void compute_stats(const Container &data,
900 std::decay_t<decltype(*std::begin(data))> &avg,
901 std::decay_t<decltype(*std::begin(data))> &var,
902 std::decay_t<decltype(*std::begin(data))> &med,
903 std::decay_t<decltype(*std::begin(data))> &_min,
904 std::decay_t<decltype(*std::begin(data))> &_max)
905{
906 using T = std::decay_t<decltype(*std::begin(data))>;
907
909 for (const auto &x : data)
910 sorted.append(x);
911 if (sorted.is_empty())
912 {
913 avg = var = med = _min = _max = T();
914 return;
915 }
916
918
919 _min = sorted[0];
920 _max = sorted[sorted.size() - 1];
921
922 const size_t n = sorted.size();
923 const size_t mid = n / 2;
924 if (n % 2 == 0)
925 med = (sorted[mid - 1] + sorted[mid]) / 2;
926 else
927 med = sorted[mid];
928
929 // Welford's algorithm for mean and variance
930 T m = T();
931 T m2 = T();
932 size_t k = 0;
933 for (size_t si = 0; si < n; ++si)
934 {
935 const auto &x = sorted[si];
936 ++k;
937 T delta = x - m;
938 m += delta / static_cast<T>(k);
939 T delta2 = x - m;
940 m2 += delta * delta2;
941 }
942
943 avg = m;
944 var = (n > 1) ? m2 / static_cast<T>(n - 1) : T();
945}
946
947} // namespace Aleph
948
949// Export commonly used functions to global namespace
955using Aleph::histogram;
956using Aleph::iqr;
957using Aleph::kurtosis;
958using Aleph::max_value;
959using Aleph::mean;
960using Aleph::median;
961using Aleph::min_max;
962using Aleph::min_value;
963using Aleph::mode;
965using Aleph::quartiles;
966using Aleph::skewness;
967using Aleph::Stats;
968using Aleph::stddev;
969using Aleph::sum;
970using Aleph::variance;
971
972#endif // STAT_UTILS_H
Exception handling system with formatted messages for Aleph-w.
#define ah_invalid_argument_if(C)
Throws std::invalid_argument if condition holds.
Definition ah-errors.H:644
High-level sorting functions for Aleph containers.
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:138
T & append(const T &data)
Append a copy of data
Definition tpl_array.H:250
Generic key-value map implemented on top of a binary search tree.
iterator begin() noexcept
Return an STL-compatible iterator to the first element.
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
static mpfr_t y
Definition mpfr_mul_d.c:3
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
auto percentile(const Container &data, double p) -> std::decay_t< decltype(*std::begin(data))>
Compute a percentile value.
Definition stat_utils.H:352
auto histogram(const Container &data, size_t num_bins) -> std::vector< std::pair< std::decay_t< decltype(*std::begin(data))>, size_t > >
Compute a histogram of the data.
Definition stat_utils.H:717
auto variance(const Container &data, bool population=false) -> std::decay_t< decltype(*std::begin(data))>
Compute variance using Welford's numerically stable algorithm.
Definition stat_utils.H:220
auto kurtosis(const Container &data) -> std::decay_t< decltype(*std::begin(data))>
Compute excess kurtosis (measure of tailedness).
Definition stat_utils.H:564
const T * median(const T &a, const T &b, const T &c, const Compare &cmp=Compare())
Return a pointer to the median value among three elements.
Definition ahUtils.H:84
and
Check uniqueness with explicit hash + equality functors.
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:105
DynArray< T > & in_place_sort(DynArray< T > &c, Cmp cmp=Cmp())
Sorts a DynArray in place.
Definition ahSort.H:328
auto covariance(const Container1 &x, const Container2 &y, bool population=false) -> std::decay_t< decltype(*std::begin(x))>
Compute covariance between two datasets.
Definition stat_utils.H:630
auto stddev(const Container &data, bool population=false) -> std::decay_t< decltype(*std::begin(data))>
Compute standard deviation.
Definition stat_utils.H:257
auto mean(const Container &data) -> std::decay_t< decltype(*std::begin(data))>
Compute the arithmetic mean.
Definition stat_utils.H:190
bool diff(const C1 &c1, const C2 &c2, Eq e=Eq())
Check if two containers differ.
auto min_max(const Container &data) -> std::pair< std::decay_t< decltype(*std::begin(data))>, std::decay_t< decltype(*std::begin(data))> >
Compute minimum and maximum values in one pass.
Definition stat_utils.H:316
auto min_value(const Container &data) -> std::decay_t< decltype(*std::begin(data))>
Compute minimum value.
Definition stat_utils.H:272
auto skewness(const Container &data) -> std::decay_t< decltype(*std::begin(data))>
Compute skewness (measure of asymmetry).
Definition stat_utils.H:523
auto iqr(const Container &data) -> std::decay_t< decltype(*std::begin(data))>
Compute the interquartile range (IQR = Q3 - Q1).
Definition stat_utils.H:426
auto compute_all_stats(const Container &data) -> Stats< std::decay_t< decltype(*std::begin(data))> >
Compute all statistics for a dataset.
Definition stat_utils.H:769
auto correlation(const Container1 &x, const Container2 &y) -> std::decay_t< decltype(*std::begin(x))>
Compute Pearson correlation coefficient.
Definition stat_utils.H:688
Container< T > range(const T start, const T end, const T step=1)
Generate a range of values [start, end] with a given step.
bool is_multimodal(const Container &data)
Check if data is multimodal.
Definition stat_utils.H:480
auto coefficient_of_variation(const Container &data) -> std::decay_t< decltype(*std::begin(data))>
Compute coefficient of variation (CV = stddev / mean).
Definition stat_utils.H:605
auto mode(const Container &data) -> std::decay_t< decltype(*std::begin(data))>
Compute the mode (most frequent value).
Definition stat_utils.H:447
auto quartiles(const Container &data) -> std::tuple< std::decay_t< decltype(*std::begin(data))>, std::decay_t< decltype(*std::begin(data))>, std::decay_t< decltype(*std::begin(data))> >
Compute quartiles (Q1, Q2, Q3).
Definition stat_utils.H:406
auto max_value(const Container &data) -> std::decay_t< decltype(*std::begin(data))>
Compute maximum value.
Definition stat_utils.H:294
void compute_stats(T *data, int l, int r, T &avg, T &var, T &med, T &_min, T &_max)
Compute basic descriptive statistics for an array range.
Definition stat_utils.H:847
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
Container for comprehensive statistical results.
Definition stat_utils.H:125
T q1
First quartile (25th percentile)
Definition stat_utils.H:134
size_t count
Number of elements.
Definition stat_utils.H:126
T min
Minimum value.
Definition stat_utils.H:132
T mean
Arithmetic mean.
Definition stat_utils.H:128
T skewness
Skewness (asymmetry)
Definition stat_utils.H:137
T q3
Third quartile (75th percentile)
Definition stat_utils.H:135
T variance
Sample variance.
Definition stat_utils.H:129
T coef_variation
Coefficient of variation (stddev/mean)
Definition stat_utils.H:139
T max
Maximum value.
Definition stat_utils.H:133
T median
Median (50th percentile)
Definition stat_utils.H:131
bool is_valid() const noexcept
Check if statistics are valid.
Definition stat_utils.H:145
T iqr
Interquartile range (Q3 - Q1)
Definition stat_utils.H:136
T range() const noexcept
Get the range (max - min).
Definition stat_utils.H:154
T kurtosis
Excess kurtosis (tailedness)
Definition stat_utils.H:138
T stddev
Standard deviation.
Definition stat_utils.H:130
T sum
Sum of all values.
Definition stat_utils.H:127
FooMap m(5, fst_unit_pair_hash, snd_unit_pair_hash)
static int * k
gsl_rng * r
Lazy and scalable dynamic array implementation.
Dynamic key-value map based on balanced binary search trees.
Comprehensive sorting algorithms and search utilities for Aleph-w.
DynList< int > l