| 
									
										
										
										
											2022-07-20 09:07:00 +02:00
										 |  |  | // Copyright 2020 Mobilinkd LLC.
 | 
					
						
							| 
									
										
										
										
											2022-06-07 03:22:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <array>
 | 
					
						
							|  |  |  | #include <algorithm>
 | 
					
						
							|  |  |  | #include <numeric>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-04 23:03:07 +02:00
										 |  |  | namespace modemm17 | 
					
						
							| 
									
										
										
										
											2022-06-07 03:22:18 +02:00
										 |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 20:12:35 +02:00
										 |  |  | template <size_t N = 10> | 
					
						
							| 
									
										
										
										
											2022-06-07 03:22:18 +02:00
										 |  |  | struct DeviationError | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     DeviationError() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-07-27 18:57:19 +02:00
										 |  |  |         minima_.fill(0.0f); | 
					
						
							|  |  |  |         maxima_.fill(0.0f); | 
					
						
							| 
									
										
										
										
											2022-06-07 03:22:18 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-06-09 20:12:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     float operator()(float sample) | 
					
						
							| 
									
										
										
										
											2022-06-07 03:22:18 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         if (sample > ZERO) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if (sample > max_estimate_ * 0.67 or max_count_ == 5) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 max_count_ = 0; | 
					
						
							|  |  |  |                 maxima_[max_index_++] = sample; | 
					
						
							|  |  |  |                 if (max_index_ == N) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     max_rolled_ = true; | 
					
						
							|  |  |  |                     max_index_ = 0; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if (max_rolled_) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     max_estimate_ = std::accumulate(std::begin(maxima_), std::end(maxima_), ZERO) / N; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     max_estimate_ = std::accumulate(std::begin(maxima_), std::begin(maxima_) + max_index_, ZERO) / max_index_; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 ++max_count_; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (sample < 0) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if (sample < min_estimate_ * 0.67 or min_count_ == 5) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 min_count_ = 0; | 
					
						
							|  |  |  |                 minima_[min_index_++] = sample; | 
					
						
							|  |  |  |                 if (min_index_ == N) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     min_rolled_ = true; | 
					
						
							|  |  |  |                     min_index_ = 0; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if (min_rolled_) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     min_estimate_ = std::accumulate(std::begin(minima_), std::end(minima_), ZERO) / N; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     min_estimate_ = std::accumulate(std::begin(minima_), std::begin(minima_) + min_index_, ZERO) / min_index_; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 ++min_count_; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-27 18:57:19 +02:00
										 |  |  |         float deviation = max_estimate_ - min_estimate_; | 
					
						
							|  |  |  |         float deviation_error = std::min(6.0f / deviation, 100.0f); | 
					
						
							| 
									
										
										
										
											2022-06-07 03:22:18 +02:00
										 |  |  |         return deviation_error; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-07-27 18:57:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     std::array<float, N> minima_; | 
					
						
							|  |  |  |     std::array<float, N> maxima_; | 
					
						
							|  |  |  |     size_t min_index_ = 0; | 
					
						
							|  |  |  |     size_t max_index_ = 0; | 
					
						
							|  |  |  |     bool min_rolled_ = false; | 
					
						
							|  |  |  |     bool max_rolled_ = false; | 
					
						
							|  |  |  |     size_t min_count_ = 0; | 
					
						
							|  |  |  |     size_t max_count_ = 0; | 
					
						
							|  |  |  |     float min_estimate_ = 0.0f; | 
					
						
							|  |  |  |     float max_estimate_ = 0.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const float ZERO = 0.0f; | 
					
						
							| 
									
										
										
										
											2022-06-07 03:22:18 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-04 23:03:07 +02:00
										 |  |  | } // modemm17
 |