22 SlidingMedian(
const unsigned int n) : window_size(2 * n + 1) {};
24 void Add(
const double value)
26 if(low.empty() || value <= *low.rbegin()) {
36 void Remove(
const double value)
38 auto it = low.find(value);
44 it = high.find(value);
46 if(it != high.end()) {
56 if(window_size % 2 == 1) {
60 return (*low.rbegin() + *high.begin()) / 2;
65 unsigned int window_size;
68 std::multiset<double> high, low;
72 if(low.size() > high.size() + 1) {
73 high.insert(*low.rbegin());
74 low.erase(low.find(*low.rbegin()));
76 else if(high.size() > low.size()) {
77 low.insert(*high.begin());
78 high.erase(high.begin());
88const std::vector<double>
MovingMedian(
const std::vector<double> & y,
const unsigned int n)
91 throw std::invalid_argument(
"MovingMedian(): the length of y is zero.");
95 throw std::invalid_argument(
"MovingMedian(): n is zero.");
98 unsigned int points = 2 * n + 1;
99 SlidingMedian smed(n);
100 std::vector<double> yy(y.size() + 2 * n), result;
102 std::fill_n(yy.begin(), n, y.front());
103 std::copy(y.begin(), y.end(), yy.begin() + n);
104 std::fill_n(yy.begin() + n + y.size(), n, y.back());
106 result.reserve(y.size());
108 for(
unsigned int i = 0; i < yy.size(); i++) {
112 smed.Remove(yy[i - points]);
116 result.emplace_back(smed.Median());