allow median() to be called with sorted array
Costa Tsaousis (ktsaou) committed
Apr 26, 2017 at 10:25 UTC
337b2007a14b77106219586363fdc05115e37bee
2 files changed
+36
-8
src/statistical.c
+32
-8
@@ -64,7 +64,17 @@ static int qsort_compare(const void *a, const void *b) {
64
return 0;
65
}
66
67
-long double median(long double *series, size_t entries) {
67
+inline void sort_series(long double *series, size_t entries) {
68
+ qsort(series, entries, sizeof(long double), qsort_compare);
69
+}
70
+
71
+inline long double *copy_series(long double *series, size_t entries) {
72
+ long double *copy = mallocz(sizeof(long double) * entries);
73
+ memcpy(copy, series, sizeof(long double) * entries);
74
+ return copy;
75
+}
76
+
77
+long double median_on_sorted_series(long double *series, size_t entries) {
78
if(unlikely(entries == 0))
79
return NAN;
80
@@ -74,19 +84,33 @@ long double median(long double *series, size_t entries) {
84
if(unlikely(entries == 2))
85
return (series[0] + series[1]) / 2;
86
77
- long double *copy = mallocz(sizeof(long double) * entries);
78
- memcpy(copy, series, sizeof(long double) * entries);
79
- qsort(copy, entries, sizeof(long double), qsort_compare);
80
-
87
long double avg;
88
if(entries % 2 == 0) {
89
size_t m = entries / 2;
84
- avg = (copy[m] + copy[m + 1]) / 2;
90
+ avg = (series[m] + series[m + 1]) / 2;
91
}
92
else {
87
- avg = copy[entries / 2];
93
+ avg = series[entries / 2];
94
}
95
96
+ return avg;
97
+}
98
+
99
+long double median(long double *series, size_t entries) {
100
+ if(unlikely(entries == 0))
101
+ return NAN;
102
+
103
+ if(unlikely(entries == 1))
104
+ return series[0];
105
+
106
+ if(unlikely(entries == 2))
107
+ return (series[0] + series[1]) / 2;
108
+
109
+ long double *copy = copy_series(series, entries);
110
+ sort_series(copy, entries);
111
+
112
+ long double avg = median_on_sorted_series(copy, entries);
113
+
114
freez(copy);
115
return avg;
116
}
@@ -98,7 +122,7 @@ long double moving_median(long double *series, size_t entries, size_t period) {
122
return median(series, entries);
123
124
size_t len = entries - period;
101
- long double *data = mallocz(sizeof(long double) * len);
125
+ long double *data = copy_series(series, entries);
126
127
size_t i;
128
for(i = period; i < entries; i++) {
src/statistical.h
+4
@@ -11,4 +11,8 @@ extern long double single_exponential_smoothing(long double *series, size_t entr
11
extern long double double_exponential_smoothing(long double *series, size_t entries, long double alpha, long double beta, long double *forecast);
12
extern long double holtwinters(long double *series, size_t entries, long double alpha, long double beta, long double gamma, long double *forecast);
13
14
+extern long double median_on_sorted_series(long double *series, size_t entries);
15
+extern long double *copy_series(long double *series, size_t entries);
16
+extern void sort_series(long double *series, size_t entries);
17
+
18
#endif //NETDATA_STATISTICAL_H