Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
stat_utils_test.cc
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
32
38#include <gtest/gtest.h>
39#include <vector>
40#include <array>
41#include <list>
42#include <cmath>
43#include <stat_utils.H>
44
45using namespace std;
46using namespace Aleph;
47
48// =============================================================================
49// Sum Tests
50// =============================================================================
51
53{
54 vector<double> v;
55 EXPECT_DOUBLE_EQ(sum(v), 0.0);
56}
57
59{
60 vector<double> v = {5.0};
61 EXPECT_DOUBLE_EQ(sum(v), 5.0);
62}
63
65{
66 vector<double> v = {1.0, 2.0, 3.0, 4.0, 5.0};
67 EXPECT_DOUBLE_EQ(sum(v), 15.0);
68}
69
71{
72 vector<double> v = {-1.0, -2.0, 3.0};
73 EXPECT_DOUBLE_EQ(sum(v), 0.0);
74}
75
77{
78 vector<int> v = {1, 2, 3, 4, 5};
79 EXPECT_EQ(sum(v), 15);
80}
81
82// =============================================================================
83// Mean Tests
84// =============================================================================
85
87{
88 vector<double> v;
89 EXPECT_THROW(mean(v), invalid_argument);
90}
91
93{
94 vector<double> v = {5.0};
95 EXPECT_DOUBLE_EQ(mean(v), 5.0);
96}
97
99{
100 vector<double> v = {1.0, 2.0, 3.0, 4.0, 5.0};
101 EXPECT_DOUBLE_EQ(mean(v), 3.0);
102}
103
105{
106 vector<double> v = {-10.0, 10.0};
107 EXPECT_DOUBLE_EQ(mean(v), 0.0);
108}
109
111{
112 list<double> l = {1.0, 2.0, 3.0};
113 EXPECT_DOUBLE_EQ(mean(l), 2.0);
114}
115
116// =============================================================================
117// Variance Tests
118// =============================================================================
119
121{
122 vector<double> v;
123 EXPECT_THROW(variance(v), invalid_argument);
124}
125
127{
128 vector<double> v = {5.0};
129 EXPECT_THROW(variance(v, false), invalid_argument); // Sample variance
130}
131
133{
134 vector<double> v = {5.0};
135 EXPECT_DOUBLE_EQ(variance(v, true), 0.0); // Population variance
136}
137
139{
140 vector<double> v = {0.0, 2.0};
141 // Sample variance: ((0-1)^2 + (2-1)^2) / 1 = 2
142 EXPECT_DOUBLE_EQ(variance(v, false), 2.0);
143}
144
146{
147 vector<double> v = {1.0, 2.0, 3.0, 4.0, 5.0};
148 double sample_var = variance(v, false);
149 double pop_var = variance(v, true);
150 // Sample variance should be larger (n-1 divisor vs n)
152}
153
155{
156 vector<double> v = {5.0, 5.0, 5.0, 5.0};
157 EXPECT_DOUBLE_EQ(variance(v), 0.0);
158}
159
161{
162 // Test Welford's algorithm with large values
163 vector<double> v = {1e10, 1e10 + 1, 1e10 + 2};
164 double var = variance(v);
165 EXPECT_NEAR(var, 1.0, 1e-6);
166}
167
168// =============================================================================
169// Standard Deviation Tests
170// =============================================================================
171
173{
174 vector<double> v = {2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0};
175 double s = stddev(v);
176 // Sample stddev of this data is approximately 2.14
177 EXPECT_NEAR(s, 2.14, 0.1);
178}
179
181{
182 vector<double> v = {1.0, 2.0, 3.0, 4.0, 5.0};
183 EXPECT_NEAR(stddev(v), sqrt(variance(v)), 1e-10);
184}
185
186// =============================================================================
187// Min/Max Tests
188// =============================================================================
189
191{
192 vector<double> v;
193 EXPECT_THROW(min_value(v), invalid_argument);
194 EXPECT_THROW(max_value(v), invalid_argument);
195 EXPECT_THROW(min_max(v), invalid_argument);
196}
197
199{
200 vector<double> v = {5.0};
203 auto [min_v, max_v] = min_max(v);
206}
207
209{
210 vector<double> v = {3.0, 1.0, 4.0, 1.0, 5.0, 9.0, 2.0};
213 auto [min_v, max_v] = min_max(v);
216}
217
219{
220 vector<double> v = {-5.0, -1.0, -10.0, -3.0};
221 EXPECT_DOUBLE_EQ(min_value(v), -10.0);
222 EXPECT_DOUBLE_EQ(max_value(v), -1.0);
223}
224
225// =============================================================================
226// Percentile Tests
227// =============================================================================
228
230{
231 vector<double> v;
232 EXPECT_THROW(percentile(v, 50), invalid_argument);
233}
234
236{
237 vector<double> v = {1.0, 2.0, 3.0};
238 EXPECT_THROW(percentile(v, -1), invalid_argument);
239 EXPECT_THROW(percentile(v, 101), invalid_argument);
240}
241
243{
244 vector<double> v = {1.0, 2.0, 3.0, 4.0, 5.0};
245 EXPECT_DOUBLE_EQ(percentile(v, 0), 1.0);
246}
247
249{
250 vector<double> v = {1.0, 2.0, 3.0, 4.0, 5.0};
251 EXPECT_DOUBLE_EQ(percentile(v, 100), 5.0);
252}
253
255{
256 vector<double> v = {1.0, 2.0, 3.0, 4.0, 5.0};
258}
259
261{
262 vector<double> v = {5.0, 1.0, 3.0, 2.0, 4.0};
263 EXPECT_DOUBLE_EQ(percentile(v, 50), 3.0);
264}
265
266// =============================================================================
267// Median Tests
268// =============================================================================
269
271{
272 vector<double> v;
273 EXPECT_THROW(median(v), invalid_argument);
274}
275
277{
278 vector<double> v = {5.0};
279 EXPECT_DOUBLE_EQ(median(v), 5.0);
280}
281
283{
284 vector<double> v = {1.0, 2.0, 3.0, 4.0, 5.0};
285 EXPECT_DOUBLE_EQ(median(v), 3.0);
286}
287
289{
290 vector<double> v = {1.0, 2.0, 3.0, 4.0};
291 EXPECT_DOUBLE_EQ(median(v), 2.5);
292}
293
295{
296 vector<double> v = {5.0, 1.0, 3.0};
297 EXPECT_DOUBLE_EQ(median(v), 3.0);
298}
299
300// =============================================================================
301// Quartiles and IQR Tests
302// =============================================================================
303
305{
306 vector<double> v = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0};
307 auto [q1, q2, q3] = quartiles(v);
308 EXPECT_NEAR(q1, 3.25, 0.01);
309 EXPECT_NEAR(q2, 5.5, 0.01);
310 EXPECT_NEAR(q3, 7.75, 0.01);
311}
312
314{
315 vector<double> v = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0};
316 auto [q1, q2, q3] = quartiles(v);
317 EXPECT_NEAR(iqr(v), q3 - q1, 0.01);
318}
319
320// =============================================================================
321// Mode Tests
322// =============================================================================
323
325{
326 vector<int> v;
327 EXPECT_THROW(mode(v), invalid_argument);
328}
329
331{
332 vector<int> v = {5};
333 EXPECT_EQ(mode(v), 5);
334}
335
337{
338 vector<int> v = {1, 2, 3, 4, 5};
339 // When all frequencies are equal, returns first encountered
340 int m = mode(v);
341 EXPECT_TRUE(m >= 1 and m <= 5);
342}
343
345{
346 vector<int> v = {1, 2, 2, 3, 3, 3, 4};
347 EXPECT_EQ(mode(v), 3);
348}
349
351{
352 vector<int> v = {1, 1, 2, 2, 3};
354}
355
357{
358 vector<int> v = {1, 2, 2, 3};
360}
361
362// =============================================================================
363// Skewness Tests
364// =============================================================================
365
367{
368 vector<double> v = {1.0, 2.0};
369 EXPECT_THROW(skewness(v), invalid_argument);
370}
371
373{
374 vector<double> v = {1.0, 2.0, 3.0, 4.0, 5.0};
375 EXPECT_NEAR(skewness(v), 0.0, 0.1);
376}
377
379{
380 vector<double> v = {1.0, 1.0, 1.0, 1.0, 10.0};
381 EXPECT_GT(skewness(v), 0.0); // Positive skewness
382}
383
385{
386 vector<double> v = {10.0, 10.0, 10.0, 10.0, 1.0};
387 EXPECT_LT(skewness(v), 0.0); // Negative skewness
388}
389
391{
392 vector<double> v = {5.0, 5.0, 5.0, 5.0};
393 EXPECT_DOUBLE_EQ(skewness(v), 0.0);
394}
395
396// =============================================================================
397// Kurtosis Tests
398// =============================================================================
399
401{
402 vector<double> v = {1.0, 2.0, 3.0};
403 EXPECT_THROW(kurtosis(v), invalid_argument);
404}
405
407{
408 // Uniform distribution has negative excess kurtosis
409 vector<double> v = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0};
410 double k = kurtosis(v);
411 EXPECT_LT(k, 0.0); // Platykurtic
412}
413
415{
416 vector<double> v = {5.0, 5.0, 5.0, 5.0, 5.0};
417 EXPECT_DOUBLE_EQ(kurtosis(v), 0.0);
418}
419
420// =============================================================================
421// Coefficient of Variation Tests
422// =============================================================================
423
425{
426 vector<double> v = {-1.0, 1.0};
427 EXPECT_THROW(coefficient_of_variation(v), invalid_argument);
428}
429
431{
432 vector<double> v = {10.0, 10.0, 10.0, 10.0};
434}
435
437{
438 vector<double> v = {1.0, 2.0, 3.0, 4.0, 5.0};
439 double cv = coefficient_of_variation(v);
440 EXPECT_GT(cv, 0.0);
441}
442
443// =============================================================================
444// Covariance Tests
445// =============================================================================
446
448{
449 vector<double> x = {1.0, 2.0, 3.0};
450 vector<double> y = {1.0, 2.0};
451 EXPECT_THROW(covariance(x, y), invalid_argument);
452}
453
455{
456 vector<double> x = {1.0};
457 vector<double> y = {1.0};
458 EXPECT_THROW(covariance(x, y, false), invalid_argument);
459}
460
462{
463 vector<double> x = {1.0, 2.0, 3.0, 4.0, 5.0};
464 vector<double> y = {1.0, 2.0, 3.0, 4.0, 5.0};
465 EXPECT_GT(covariance(x, y), 0.0);
466}
467
469{
470 vector<double> x = {1.0, 2.0, 3.0, 4.0, 5.0};
471 vector<double> y = {5.0, 4.0, 3.0, 2.0, 1.0};
472 EXPECT_LT(covariance(x, y), 0.0);
473}
474
476{
477 vector<double> x = {1.0, 2.0, 3.0};
478 vector<double> y = {2.0, 2.0, 2.0}; // Constant
479 EXPECT_NEAR(covariance(x, y), 0.0, 1e-10);
480}
481
482// =============================================================================
483// Correlation Tests
484// =============================================================================
485
487{
488 vector<double> x = {1.0, 2.0, 3.0, 4.0, 5.0};
489 vector<double> y = {2.0, 4.0, 6.0, 8.0, 10.0};
490 EXPECT_NEAR(correlation(x, y), 1.0, 1e-10);
491}
492
494{
495 vector<double> x = {1.0, 2.0, 3.0, 4.0, 5.0};
496 vector<double> y = {10.0, 8.0, 6.0, 4.0, 2.0};
497 EXPECT_NEAR(correlation(x, y), -1.0, 1e-10);
498}
499
501{
502 vector<double> x = {1.0, 1.0, 1.0}; // Constant
503 vector<double> y = {1.0, 2.0, 3.0};
504 EXPECT_THROW(correlation(x, y), invalid_argument);
505}
506
508{
509 vector<double> x = {1.0, 2.0, 3.0, 4.0, 5.0};
510 vector<double> y = {1.0, 2.0, 1.5, 3.5, 5.0};
511 double r = correlation(x, y);
512 EXPECT_GT(r, 0.0);
513 EXPECT_LT(r, 1.0);
514}
515
516// =============================================================================
517// Histogram Tests
518// =============================================================================
519
521{
522 vector<double> v = {1.0, 2.0, 3.0};
523 EXPECT_THROW(histogram(v, 0), invalid_argument);
524}
525
527{
528 vector<double> v;
529 EXPECT_THROW(histogram(v, 5), invalid_argument);
530}
531
533{
534 vector<double> v = {1.0, 2.0, 3.0, 4.0, 5.0};
535 auto h = histogram(v, 1);
536 EXPECT_EQ(h.size(), 1u);
537 EXPECT_EQ(h[0].second, 5u); // All in one bin
538}
539
541{
542 vector<double> v = {1.0, 2.0, 3.0, 4.0, 5.0};
543 auto h = histogram(v, 5);
544 EXPECT_EQ(h.size(), 5u);
545 // Each value should fall into its own bin
546 size_t total = 0;
547 for (const auto & [center, count] : h)
548 total += count;
549 EXPECT_EQ(total, 5u);
550}
551
553{
554 vector<double> v = {5.0, 5.0, 5.0, 5.0};
555 auto h = histogram(v, 3);
556 // All values are equal, should be in single bin
557 EXPECT_EQ(h.size(), 1u);
558 EXPECT_EQ(h[0].second, 4u);
559}
560
561// =============================================================================
562// Stats Structure Tests
563// =============================================================================
564
571
573{
575 s.min = 1.0;
576 s.max = 10.0;
577 EXPECT_DOUBLE_EQ(s.range(), 9.0);
578}
579
580// =============================================================================
581// compute_all_stats Tests
582// =============================================================================
583
585{
586 vector<double> v;
587 auto s = compute_all_stats(v);
588 EXPECT_EQ(s.count, 0u);
589 EXPECT_FALSE(s.is_valid());
590}
591
593{
594 vector<double> v = {5.0};
595 auto s = compute_all_stats(v);
596 EXPECT_EQ(s.count, 1u);
597 EXPECT_TRUE(s.is_valid());
598 EXPECT_DOUBLE_EQ(s.mean, 5.0);
599 EXPECT_DOUBLE_EQ(s.sum, 5.0);
600 EXPECT_DOUBLE_EQ(s.min, 5.0);
601 EXPECT_DOUBLE_EQ(s.max, 5.0);
602 EXPECT_DOUBLE_EQ(s.median, 5.0);
603}
604
606{
607 vector<double> v = {1.0, 2.0, 3.0, 4.0, 5.0};
608 auto s = compute_all_stats(v);
609
610 EXPECT_EQ(s.count, 5u);
611 EXPECT_DOUBLE_EQ(s.sum, 15.0);
612 EXPECT_DOUBLE_EQ(s.mean, 3.0);
613 EXPECT_DOUBLE_EQ(s.min, 1.0);
614 EXPECT_DOUBLE_EQ(s.max, 5.0);
615 EXPECT_DOUBLE_EQ(s.median, 3.0);
616 EXPECT_GT(s.variance, 0.0);
617 EXPECT_GT(s.stddev, 0.0);
618 EXPECT_DOUBLE_EQ(s.range(), 4.0);
619}
620
622{
623 vector<double> v = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0};
624 auto s = compute_all_stats(v);
625
626 EXPECT_LT(s.q1, s.median);
627 EXPECT_LT(s.median, s.q3);
628 EXPECT_NEAR(s.iqr, s.q3 - s.q1, 0.001);
629}
630
632{
633 vector<double> v = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0};
634 auto s = compute_all_stats(v);
635
636 // Symmetric distribution should have skewness near 0
637 EXPECT_NEAR(s.skewness, 0.0, 0.1);
638 // Kurtosis is computed for 10+ elements
639 // Uniform has negative excess kurtosis
640 EXPECT_LT(s.kurtosis, 0.0);
641}
642
643// =============================================================================
644// Legacy compute_stats Tests (backward compatibility)
645// =============================================================================
646
648{
649 double data[] = {5.0, 1.0, 3.0, 2.0, 4.0};
650 double avg, var, med, min_val, max_val;
651
652 compute_stats(data, 0, 4, avg, var, med, min_val, max_val);
653
654 EXPECT_DOUBLE_EQ(avg, 3.0);
655 EXPECT_DOUBLE_EQ(med, 3.0);
658 EXPECT_GT(var, 0.0);
659}
660
662{
663 double data[] = {100.0, 1.0, 2.0, 3.0, 100.0};
664 double avg, var, med, min_val, max_val;
665
666 // Only use data[1..3]
667 compute_stats(data, 1, 3, avg, var, med, min_val, max_val);
668
669 EXPECT_DOUBLE_EQ(avg, 2.0);
670 EXPECT_DOUBLE_EQ(med, 2.0);
673}
674
676{
677 vector<double> v = {5.0, 1.0, 3.0, 2.0, 4.0};
678 double avg, var, med, min_val, max_val;
679
680 compute_stats(v, avg, var, med, min_val, max_val);
681
682 EXPECT_DOUBLE_EQ(avg, 3.0);
683 EXPECT_DOUBLE_EQ(med, 3.0);
686}
687
689{
690 double data[] = {1.0, 2.0, 3.0, 4.0};
691 double avg, var, med, min_val, max_val;
692
693 compute_stats(data, 0, 3, avg, var, med, min_val, max_val);
694
695 EXPECT_DOUBLE_EQ(med, 2.5); // (2+3)/2
696}
697
699{
700 double data[] = {1.0, 2.0, 3.0};
701 double avg, var, med, min_val, max_val;
702
703 // l > r means empty range
704 compute_stats(data, 2, 1, avg, var, med, min_val, max_val);
705
706 EXPECT_DOUBLE_EQ(avg, 0.0);
707 EXPECT_DOUBLE_EQ(var, 0.0);
708 EXPECT_DOUBLE_EQ(med, 0.0);
709}
710
711// =============================================================================
712// Edge Cases and Numerical Stability
713// =============================================================================
714
716{
717 vector<double> v = {1e15, 1e15 + 1, 1e15 + 2, 1e15 + 3, 1e15 + 4};
718 auto s = compute_all_stats(v);
719
720 // Mean should be accurate
721 EXPECT_NEAR(s.mean, 1e15 + 2, 1.0);
722 // Variance should be stable (Welford's algorithm)
723 EXPECT_NEAR(s.variance, 2.5, 0.1);
724}
725
727{
728 vector<double> v = {1e-15, 2e-15, 3e-15, 4e-15, 5e-15};
729 auto s = compute_all_stats(v);
730
731 EXPECT_NEAR(s.mean, 3e-15, 1e-16);
732 EXPECT_GT(s.variance, 0.0);
733}
734
736{
737 vector<double> v = {-100.0, -50.0, 0.0, 50.0, 100.0};
738 auto s = compute_all_stats(v);
739
740 EXPECT_DOUBLE_EQ(s.mean, 0.0);
741 EXPECT_DOUBLE_EQ(s.median, 0.0);
742}
743
744// =============================================================================
745// Container Type Tests
746// =============================================================================
747
749{
750 array<double, 5> a = {1.0, 2.0, 3.0, 4.0, 5.0};
751 EXPECT_DOUBLE_EQ(mean(a), 3.0);
752 EXPECT_DOUBLE_EQ(median(a), 3.0);
753}
754
756{
757 list<double> l = {1.0, 2.0, 3.0, 4.0, 5.0};
758 EXPECT_DOUBLE_EQ(mean(l), 3.0);
760}
761
763{
765 a.append(1.0);
766 a.append(2.0);
767 a.append(3.0);
768 a.append(4.0);
769 a.append(5.0);
770
771 EXPECT_DOUBLE_EQ(mean(a), 3.0);
772 auto s = compute_all_stats(a);
773 EXPECT_EQ(s.count, 5u);
774}
775
776// =============================================================================
777// Type Tests
778// =============================================================================
779
781{
782 vector<int> v = {1, 2, 3, 4, 5};
783 EXPECT_EQ(sum(v), 15);
784 EXPECT_EQ(mode(v), 1); // All unique, returns first
785}
786
788{
789 vector<float> v = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
790 EXPECT_FLOAT_EQ(mean(v), 3.0f);
791}
792
793int main(int argc, char **argv)
794{
795 ::testing::InitGoogleTest(&argc, argv);
796 return RUN_ALL_TESTS();
797}
int main()
long double h
Definition btreepic.C:154
T & append()
Allocate a new entry to the end of array.
#define TEST(name)
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_sqrt_function > > sqrt(const __gmp_expr< T, U > &expr)
Definition gmpfrxx.h:4058
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:358
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:740
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:215
auto kurtosis(const Container &data) -> std::decay_t< decltype(*std::begin(data))>
Compute excess kurtosis (measure of tailedness).
Definition stat_utils.H:579
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
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:648
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:183
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:320
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:536
auto iqr(const Container &data) -> std::decay_t< decltype(*std::begin(data))>
Compute the interquartile range (IQR = Q3 - Q1).
Definition stat_utils.H:434
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:794
auto correlation(const Container1 &x, const Container2 &y) -> std::decay_t< decltype(*std::begin(x))>
Compute Pearson correlation coefficient.
Definition stat_utils.H:711
bool is_multimodal(const Container &data)
Check if data is multimodal.
Definition stat_utils.H:493
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:622
auto mode(const Container &data) -> std::decay_t< decltype(*std::begin(data))>
Compute the mode (most frequent value).
Definition stat_utils.H:456
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:414
auto max_value(const Container &data) -> std::decay_t< decltype(*std::begin(data))>
Compute maximum value.
Definition stat_utils.H:296
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:872
DynList< T > maps(const C &c, Op op)
Classic map operation.
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.
STL namespace.
Comprehensive statistical utilities for numeric data.
Container for comprehensive statistical results.
Definition stat_utils.H:123
size_t count
Number of elements.
Definition stat_utils.H:124
T min
Minimum value.
Definition stat_utils.H:130
T max
Maximum value.
Definition stat_utils.H:131
bool is_valid() const noexcept
Check if statistics are valid.
Definition stat_utils.H:143
T range() const noexcept
Get the range (max - min).
Definition stat_utils.H:149
DynList< int > l