Skip to content

Commit 4b677fd

Browse files
authored
Merge pull request #59 from simosund/pping-agg-prototype
Add aggregation option to ePPing
2 parents 9ba9e7c + 59310e8 commit 4b677fd

File tree

4 files changed

+1620
-170
lines changed

4 files changed

+1620
-170
lines changed

pping/lhist.h

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/* SPDX-License-Identifier: GPL-2.0-or-later */
2+
#ifndef LHIST_H
3+
#define LHIST_H
4+
5+
#include <stdlib.h>
6+
#include <math.h>
7+
#include <linux/types.h>
8+
9+
#include <stdio.h>
10+
11+
/* Count total number of instances in histogram*/
12+
static __u64 lhist_count(__u32 *bins, size_t size)
13+
{
14+
__u64 count = 0;
15+
int i;
16+
for (i = 0; i < size; i++)
17+
count += bins[i];
18+
return count;
19+
}
20+
21+
static double lhist_bin_midval(int bin_idx, double bin_width, double left_edge)
22+
{
23+
return left_edge + (bin_width / 2) + bin_width * bin_idx;
24+
}
25+
26+
/* Calculate an approximate minimum value from a linear histogram.
27+
* The approximation is the middle of the first non-empty bin. */
28+
static double lhist_min(__u32 *bins, size_t size, double bin_width,
29+
double left_edge)
30+
{
31+
int i;
32+
33+
for (i = 0; i < size; i++) {
34+
if (bins[i] > 0)
35+
break;
36+
}
37+
38+
return size < 1 || bins[i] == 0 ?
39+
NAN :
40+
lhist_bin_midval(i, bin_width, left_edge);
41+
}
42+
43+
/* Calculate an approximate maximum value from a linear histogram.
44+
* The approximation is the middle of the last non-empty bin. */
45+
static double lhist_max(__u32 *bins, size_t size, double bin_width,
46+
double left_edge)
47+
{
48+
int i, last_nonempty = 0;
49+
50+
for (i = 0; i < size; i++) {
51+
if (bins[i] > 0)
52+
last_nonempty = i;
53+
}
54+
55+
return size < 1 || bins[last_nonempty] == 0 ?
56+
NAN :
57+
lhist_bin_midval(last_nonempty, bin_width, left_edge);
58+
}
59+
60+
/* Calculate an apporximate arithmetic mean from a linear histogram.
61+
* The approximation is based on the assumption that all instances are located
62+
* in the middle of their respective bins. */
63+
static double lhist_mean(__u32 *bins, size_t size, double bin_width,
64+
double left_edge)
65+
{
66+
double sum = 0, mid_val = left_edge + (bin_width / 2);
67+
__u64 count = 0;
68+
int i;
69+
70+
for (i = 0; i < size; i++) {
71+
count += bins[i];
72+
sum += bins[i] * mid_val;
73+
mid_val += bin_width;
74+
}
75+
76+
return count ? sum / count : NAN;
77+
}
78+
79+
/* Calculate an approximate percentile value from a linear histogram.
80+
* The approximation is based on the assumption that all instances are located
81+
* in the middle of their respective bins. Does linear interpolation for
82+
* percentiles located between bins (similar to ex. numpy.percentile) */
83+
static double lhist_percentile(__u32 *bins, double percentile, size_t size,
84+
double bin_width, double left_edge)
85+
{
86+
__u64 n = lhist_count(bins, size);
87+
double virt_idx, ret;
88+
int i = 0, next_i;
89+
__u64 count = 0;
90+
91+
if (n < 1)
92+
return NAN;
93+
94+
virt_idx = percentile / 100 * (n - 1);
95+
96+
/* Check for out of bounds percentiles or rounding errors*/
97+
if (virt_idx <= 0)
98+
return lhist_min(bins, size, bin_width, left_edge);
99+
else if (virt_idx >= n - 1)
100+
return lhist_max(bins, size, bin_width, left_edge);
101+
102+
/* find bin the virtual index should lie in */
103+
while (count <= virt_idx) {
104+
count += bins[i++];
105+
}
106+
i--;
107+
ret = lhist_bin_midval(i, bin_width, left_edge);
108+
109+
/* virtual index is between current bin and next (non-empty) bin
110+
(count - 1 < virt_idx < count) */
111+
if (virt_idx > count - 1) {
112+
/* Find next non-empty bin to interpolate between */
113+
next_i = i + 1;
114+
while (bins[next_i] == 0) {
115+
next_i++;
116+
}
117+
ret += (virt_idx - (count - 1)) * (next_i - i) * bin_width;
118+
}
119+
return ret;
120+
}
121+
122+
#endif

0 commit comments

Comments
 (0)