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