/* Moving Extrema Copyright 2020 Ahmet Inan */ #pragma once #include "delay.hh" #include "deque.hh" namespace DSP { template class MovExt { Deque window, dispenser, refill; EQUAL equal; COMP comp; public: TYPE operator () (TYPE input) { if (window.full()) { if (equal(window.front(), dispenser.front())) dispenser.pop_front(); window.pop_front(); } window.push_back(input); while (!refill.empty() && comp(input, refill.front())) refill.pop_front(); refill.push_front(input); if (dispenser.empty()) { while (!refill.empty()) { dispenser.push_front(refill.front()); refill.pop_front(); } return dispenser.front(); } return comp(dispenser.front(), refill.back()) ? dispenser.front() : refill.back(); } }; template class MovMin { Delay window; Deque dispenser, refill; public: MovMin() : window(std::numeric_limits::max()) { dispenser.push_front(std::numeric_limits::max()); } TYPE operator () (TYPE input) { if (window(input) == dispenser.front()) dispenser.pop_front(); while (!refill.empty() && input < refill.front()) refill.pop_front(); refill.push_front(input); if (dispenser.empty()) { while (!refill.empty()) { dispenser.push_front(refill.front()); refill.pop_front(); } return dispenser.front(); } return dispenser.front() < refill.back() ? dispenser.front() : refill.back(); } }; template class MovMax { Delay window; Deque dispenser, refill; public: MovMax() : window(std::numeric_limits::min()) { dispenser.push_front(std::numeric_limits::min()); } TYPE operator () (TYPE input) { if (window(input) == dispenser.front()) dispenser.pop_front(); while (!refill.empty() && input > refill.front()) refill.pop_front(); refill.push_front(input); if (dispenser.empty()) { while (!refill.empty()) { dispenser.push_front(refill.front()); refill.pop_front(); } return dispenser.front(); } return dispenser.front() > refill.back() ? dispenser.front() : refill.back(); } }; }