| 
									
										
										
										
											2016-06-20 00:45:24 +02:00
										 |  |  | ///////////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | //                                                                                   //
 | 
					
						
							|  |  |  | // http://stackoverflow.com/questions/10990618/calculate-rolling-moving-average-in-c //
 | 
					
						
							|  |  |  | //                                                                                   //
 | 
					
						
							|  |  |  | // Copyright (C) 2016 Edouard Griffiths, F4EXB                                       //
 | 
					
						
							|  |  |  | //                                                                                   //
 | 
					
						
							|  |  |  | // This program is free software; you can redistribute it and/or modify              //
 | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by              //
 | 
					
						
							|  |  |  | // the Free Software Foundation as version 3 of the License, or                      //
 | 
					
						
							| 
									
										
										
										
											2019-04-11 14:32:15 +02:00
										 |  |  | // (at your option) any later version.                                               //
 | 
					
						
							| 
									
										
										
										
											2016-06-20 00:45:24 +02:00
										 |  |  | //                                                                                   //
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful,                   //
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of                    //
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                      //
 | 
					
						
							|  |  |  | // GNU General Public License V3 for more details.                                   //
 | 
					
						
							|  |  |  | //                                                                                   //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU General Public License                 //
 | 
					
						
							|  |  |  | // along with this program. If not, see <http://www.gnu.org/licenses/>.              //
 | 
					
						
							|  |  |  | ///////////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-14 20:31:26 +02:00
										 |  |  | #ifndef _UTIL_MOVINGAVERAGE_H_
 | 
					
						
							|  |  |  | #define _UTIL_MOVINGAVERAGE_H_
 | 
					
						
							| 
									
										
										
										
											2016-06-20 00:45:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <algorithm>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <typename T, typename Total, int N> | 
					
						
							| 
									
										
										
										
											2017-11-06 01:02:20 +01:00
										 |  |  | class MovingAverageUtil | 
					
						
							| 
									
										
										
										
											2016-06-20 00:45:24 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   public: | 
					
						
							| 
									
										
										
										
											2017-11-06 01:02:20 +01:00
										 |  |  |     MovingAverageUtil() | 
					
						
							| 
									
										
										
										
											2018-02-03 07:17:49 +01:00
										 |  |  |       : m_num_samples(0), m_index(0), m_total(0) | 
					
						
							| 
									
										
										
										
											2016-06-20 00:45:24 +02:00
										 |  |  |     { } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-03 10:33:02 +01:00
										 |  |  |     void reset() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_num_samples = 0; | 
					
						
							|  |  |  |         m_index = 0; | 
					
						
							|  |  |  |         m_total = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-20 00:45:24 +02:00
										 |  |  |     void operator()(T sample) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-02-03 07:17:49 +01:00
										 |  |  |         if (m_num_samples < N) // fill up
 | 
					
						
							| 
									
										
										
										
											2016-06-20 00:45:24 +02:00
										 |  |  |         { | 
					
						
							|  |  |  |             m_samples[m_num_samples++] = sample; | 
					
						
							|  |  |  |             m_total += sample; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-02-03 07:17:49 +01:00
										 |  |  |         else // roll
 | 
					
						
							| 
									
										
										
										
											2016-06-20 00:45:24 +02:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2018-02-03 07:17:49 +01:00
										 |  |  |             T& oldest = m_samples[m_index]; | 
					
						
							| 
									
										
										
										
											2016-06-20 00:45:24 +02:00
										 |  |  |             m_total += sample - oldest; | 
					
						
							|  |  |  |             oldest = sample; | 
					
						
							| 
									
										
										
										
											2018-02-03 10:33:02 +01:00
										 |  |  |             m_index = (m_index + 1) % N; | 
					
						
							| 
									
										
										
										
											2016-06-20 00:45:24 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-24 10:29:27 +01:00
										 |  |  |     double asDouble() const { return ((double)m_total) / N; } | 
					
						
							|  |  |  |     float asFloat() const { return ((float)m_total) / N; } | 
					
						
							| 
									
										
										
										
											2018-02-01 02:45:55 +01:00
										 |  |  |     operator T() const { return  m_total / N; } | 
					
						
							| 
									
										
										
										
											2018-08-31 07:38:30 +02:00
										 |  |  |     T instantAverage() const { return m_total / (m_num_samples == 0 ? 1 : m_num_samples); } | 
					
						
							| 
									
										
										
										
											2016-06-20 00:45:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   private: | 
					
						
							|  |  |  |     T m_samples[N]; | 
					
						
							|  |  |  |     int m_num_samples; | 
					
						
							| 
									
										
										
										
											2018-02-03 07:17:49 +01:00
										 |  |  |     unsigned int m_index; | 
					
						
							| 
									
										
										
										
											2016-06-20 00:45:24 +02:00
										 |  |  |     Total m_total; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-15 01:03:43 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | template <typename T, typename Total> | 
					
						
							|  |  |  | class MovingAverageUtilVar | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   public: | 
					
						
							|  |  |  |     MovingAverageUtilVar(unsigned int size) | 
					
						
							|  |  |  |       : m_num_samples(0), m_index(0), m_total(0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_samples.resize(size); | 
					
						
							| 
									
										
										
										
											2020-07-20 09:34:11 +03:00
										 |  |  | 		m_samplesSizeInvF = 1.0f / size; | 
					
						
							|  |  |  | 		m_samplesSizeInvD = 1.0 / size; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-05-15 01:03:43 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     void reset() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_num_samples = 0; | 
					
						
							|  |  |  |         m_index = 0; | 
					
						
							|  |  |  |         m_total = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void resize(unsigned int size) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         reset(); | 
					
						
							|  |  |  |         m_samples.resize(size); | 
					
						
							| 
									
										
										
										
											2020-07-20 09:34:11 +03:00
										 |  |  | 		m_samplesSizeInvF = 1.0f / size; | 
					
						
							|  |  |  | 		m_samplesSizeInvD = 1.0 / size; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-05-15 01:03:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-18 19:03:54 +02:00
										 |  |  |     unsigned int size() const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return m_samples.size(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-15 01:03:43 +02:00
										 |  |  |     void operator()(T sample) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (m_num_samples < m_samples.size()) // fill up
 | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             m_samples[m_num_samples++] = sample; | 
					
						
							|  |  |  |             m_total += sample; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else // roll
 | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             T& oldest = m_samples[m_index]; | 
					
						
							|  |  |  |             m_total += sample - oldest; | 
					
						
							|  |  |  |             oldest = sample; | 
					
						
							| 
									
										
										
										
											2020-07-20 09:34:11 +03:00
										 |  |  |             m_index++; | 
					
						
							|  |  |  |             if (m_index == m_samples.size()) | 
					
						
							|  |  |  |                 m_index = 0; | 
					
						
							| 
									
										
										
										
											2018-05-15 01:03:43 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 09:34:11 +03:00
										 |  |  |     double asDouble() const { return m_total * m_samplesSizeInvD; } | 
					
						
							|  |  |  |     float asFloat() const { return m_total * m_samplesSizeInvF; } | 
					
						
							| 
									
										
										
										
											2018-05-15 01:03:43 +02:00
										 |  |  |     operator T() const { return  m_total / m_samples.size(); } | 
					
						
							| 
									
										
										
										
											2023-05-15 16:40:43 +01:00
										 |  |  |     T instantAverage() const { return m_total / (m_num_samples == 0 ? 1 : m_num_samples); } | 
					
						
							| 
									
										
										
										
											2018-05-15 01:03:43 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   private: | 
					
						
							|  |  |  |     std::vector<T> m_samples; | 
					
						
							|  |  |  |     unsigned int m_num_samples; | 
					
						
							|  |  |  |     unsigned int m_index; | 
					
						
							|  |  |  |     Total m_total; | 
					
						
							| 
									
										
										
										
											2020-07-20 09:34:11 +03:00
										 |  |  | 	float m_samplesSizeInvF; | 
					
						
							|  |  |  | 	double m_samplesSizeInvD; | 
					
						
							| 
									
										
										
										
											2018-05-15 01:03:43 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-03 01:52:11 +01:00
										 |  |  | #endif /* _UTIL_MOVINGAVERAGE_H_ */
 |