moving_average.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #ifndef __MOVING_AVERAGE_H__
  2. #define __MOVING_AVERAGE_H__
  3. #include <vector>
  4. #include <cmath>
  5. #include "fixed_types.h"
  6. #include "modulo_num.h"
  7. #include "log.h"
  8. template <class T>
  9. class MovingAverage
  10. {
  11. public:
  12. enum AvgType_t
  13. {
  14. ARITHMETIC_MEAN = 0,
  15. GEOMETRIC_MEAN,
  16. MEDIAN,
  17. NUM_AVG_TYPES
  18. };
  19. MovingAverage(UInt32 max_window_size);
  20. virtual ~MovingAverage();
  21. static AvgType_t parseAvgType(String avg_type)
  22. {
  23. if (avg_type == "arithmetic_mean")
  24. return ARITHMETIC_MEAN;
  25. else if (avg_type == "geometric_mean")
  26. return GEOMETRIC_MEAN;
  27. else if (avg_type == "median")
  28. return MEDIAN;
  29. else
  30. {
  31. LOG_PRINT_ERROR("Unsupported Average Type: %s", avg_type.c_str());
  32. return (AvgType_t) -1;
  33. }
  34. }
  35. static MovingAverage<T>* createAvgType(AvgType_t avg_type, UInt32 max_window_size);
  36. virtual void update(T next_num) = 0;
  37. virtual T compute() const = 0;
  38. virtual T compute(T next_num) { update(next_num); return compute(); }
  39. protected:
  40. std::vector<T> m_num_list;
  41. UInt32 m_max_window_size;
  42. ModuloNum m_curr_window_front;
  43. ModuloNum m_curr_window_back;
  44. void addToWindow(T next_num);
  45. void printElements()
  46. {
  47. printf("Elements: ");
  48. ModuloNum curr_num(m_curr_window_front);
  49. for ( ; curr_num != m_curr_window_back; curr_num = curr_num+1)
  50. printf("%f ", (float) m_num_list[curr_num.getValue()]);
  51. printf("\n");
  52. }
  53. };
  54. template<class T>
  55. MovingAverage<T>::MovingAverage(UInt32 max_window_size)
  56. : m_max_window_size(max_window_size)
  57. {
  58. m_num_list.resize(m_max_window_size + 1);
  59. m_curr_window_front = ModuloNum(m_max_window_size + 1);
  60. m_curr_window_back = ModuloNum(m_max_window_size + 1);
  61. }
  62. template<class T>
  63. MovingAverage<T>::~MovingAverage()
  64. { }
  65. template<class T>
  66. void MovingAverage<T>::addToWindow(T next_num)
  67. {
  68. m_num_list[m_curr_window_back.getValue()] = next_num;
  69. m_curr_window_back = m_curr_window_back + 1;
  70. if (m_curr_window_back == m_curr_window_front)
  71. {
  72. m_curr_window_front = m_curr_window_front + 1;
  73. }
  74. }
  75. template <class T>
  76. class MovingArithmeticMean : public MovingAverage<T>
  77. {
  78. private:
  79. T sum;
  80. public:
  81. MovingArithmeticMean(UInt32 max_window_size):
  82. MovingAverage<T>(max_window_size),
  83. sum(SubsecondTime::Zero())
  84. { }
  85. void update(T next_num)
  86. {
  87. UInt32 curr_window_size = (this->m_curr_window_back - this->m_curr_window_front).getValue();
  88. if (curr_window_size == this->m_max_window_size)
  89. {
  90. curr_window_size --;
  91. sum -= this->m_num_list[this->m_curr_window_front.getValue()];
  92. }
  93. sum += next_num;
  94. curr_window_size ++;
  95. this->addToWindow(next_num);
  96. }
  97. T compute() const
  98. {
  99. UInt32 curr_window_size = (this->m_curr_window_back - this->m_curr_window_front).getValue(); // recompute
  100. return sum / curr_window_size;
  101. }
  102. };
  103. template <class T>
  104. class MovingGeometricMean : public MovingAverage<T>
  105. {
  106. public:
  107. MovingGeometricMean(UInt32 max_window_size):
  108. MovingAverage<T>(max_window_size)
  109. { }
  110. void update(T next_num)
  111. {
  112. this->addToWindow(next_num);
  113. }
  114. T compute() const
  115. {
  116. UInt32 curr_window_size = (this->m_curr_window_back - this->m_curr_window_front).getValue();
  117. T geometric_mean = SubsecondTime::Zero();
  118. geometric_mean.setInternalDataForced(1);
  119. ModuloNum curr_num(this->m_curr_window_front);
  120. for ( ; curr_num != this->m_curr_window_back; curr_num = curr_num+1)
  121. geometric_mean *= this->m_num_list[curr_num.getValue()];
  122. //FIXME Use of internal data
  123. SubsecondTime ret;
  124. ret.setInternalDataForced(pow((double) geometric_mean.getInternalDataForced(), (double) 1.0/curr_window_size));
  125. return ret;
  126. }
  127. };
  128. template <class T>
  129. class MovingMedian : public MovingAverage<T>
  130. {
  131. public:
  132. MovingMedian(UInt32 max_window_size):
  133. MovingAverage<T>(max_window_size)
  134. { }
  135. void update(T next_num)
  136. {
  137. this->addToWindow(next_num);
  138. }
  139. T compute() const
  140. {
  141. UInt32 curr_window_size = (this->m_curr_window_back - this->m_curr_window_front).getValue();
  142. UInt32 median_index = (this->m_curr_window_front + (curr_window_size / 2)).getValue();
  143. return this->m_num_list[median_index];
  144. }
  145. };
  146. template <class T>
  147. MovingAverage<T>* MovingAverage<T>::createAvgType(AvgType_t avg_type, UInt32 max_window_size)
  148. {
  149. switch(avg_type)
  150. {
  151. case ARITHMETIC_MEAN:
  152. return new MovingArithmeticMean<T>(max_window_size);
  153. case GEOMETRIC_MEAN:
  154. return new MovingGeometricMean<T>(max_window_size);
  155. case MEDIAN:
  156. return new MovingMedian<T>(max_window_size);
  157. default:
  158. LOG_PRINT_ERROR("Unsupported Average Type: %u", (UInt32) avg_type);
  159. return NULL;
  160. }
  161. }
  162. #endif /* __MOVING_AVERAGE_H__ */