median.c 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "median.h"
  3. // ----------------------------------------------------------------------------
  4. // median
  5. struct grouping_median {
  6. size_t series_size;
  7. size_t next_pos;
  8. NETDATA_DOUBLE *series;
  9. };
  10. void grouping_create_median(RRDR *r, const char *options __maybe_unused) {
  11. long entries = r->group;
  12. if(entries < 0) entries = 0;
  13. struct grouping_median *g = (struct grouping_median *)onewayalloc_callocz(r->internal.owa, 1, sizeof(struct grouping_median));
  14. g->series = onewayalloc_mallocz(r->internal.owa, entries * sizeof(NETDATA_DOUBLE));
  15. g->series_size = (size_t)entries;
  16. r->internal.grouping_data = g;
  17. }
  18. // resets when switches dimensions
  19. // so, clear everything to restart
  20. void grouping_reset_median(RRDR *r) {
  21. struct grouping_median *g = (struct grouping_median *)r->internal.grouping_data;
  22. g->next_pos = 0;
  23. }
  24. void grouping_free_median(RRDR *r) {
  25. struct grouping_median *g = (struct grouping_median *)r->internal.grouping_data;
  26. if(g) onewayalloc_freez(r->internal.owa, g->series);
  27. onewayalloc_freez(r->internal.owa, r->internal.grouping_data);
  28. r->internal.grouping_data = NULL;
  29. }
  30. void grouping_add_median(RRDR *r, NETDATA_DOUBLE value) {
  31. struct grouping_median *g = (struct grouping_median *)r->internal.grouping_data;
  32. if(unlikely(g->next_pos >= g->series_size)) {
  33. g->series = onewayalloc_doublesize( r->internal.owa, g->series, g->series_size * sizeof(NETDATA_DOUBLE));
  34. g->series_size *= 2;
  35. }
  36. else
  37. g->series[g->next_pos++] = (NETDATA_DOUBLE)value;
  38. }
  39. NETDATA_DOUBLE grouping_flush_median(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr) {
  40. struct grouping_median *g = (struct grouping_median *)r->internal.grouping_data;
  41. NETDATA_DOUBLE value;
  42. if(unlikely(!g->next_pos)) {
  43. value = 0.0;
  44. *rrdr_value_options_ptr |= RRDR_VALUE_EMPTY;
  45. }
  46. else {
  47. if(g->next_pos > 1) {
  48. sort_series(g->series, g->next_pos);
  49. value = (NETDATA_DOUBLE)median_on_sorted_series(g->series, g->next_pos);
  50. }
  51. else
  52. value = (NETDATA_DOUBLE)g->series[0];
  53. if(!netdata_double_isnumber(value)) {
  54. value = 0.0;
  55. *rrdr_value_options_ptr |= RRDR_VALUE_EMPTY;
  56. }
  57. //log_series_to_stderr(g->series, g->next_pos, value, "median");
  58. }
  59. g->next_pos = 0;
  60. return value;
  61. }