#include "MinMaxLemire.h"


MinMaxLemire::MinMaxLemire(uint32_t N)
: width(N)
, minvalues(2*N)
, maxvalues(2*N)
{
}

MinMaxLemire::~MinMaxLemire(void)
{
}

void MinMaxLemire::process(vector<float> & array)
{
    maxfifo.push_back(0);
    minfifo.push_back(0);

	for (uint32_t i = 1; i < width; ++i)
	{
		if (array[i] > array[i - 1])
		{
			//overshoot
			maxfifo.pop_back();
			while (!maxfifo.empty())
			{
				if (array[i] <= array[maxfifo.back()])
					break;
			
				maxfifo.pop_back();
			}
		} 
		else
		{
			minfifo.pop_back();
			while (!minfifo.empty())
			{
				if (array[i] >= array[minfifo.back()])
					break;
			
				minfifo.pop_back();
			}
		}
		maxfifo.push_back(i);
		minfifo.push_back(i);
	}

	for (uint32_t i = width; i < array.size(); ++i)
	{
		maxvalues[i - width] = array[maxfifo.front()];
		minvalues[i - width] = array[minfifo.front()];
		if (array[i] > array[i - 1])
		{
			//overshoot
			maxfifo.pop_back();
	
			while (!maxfifo.empty())
			{
				if (array[i] <= array[maxfifo.back()])
					break;
			
				maxfifo.pop_back();
			}
		} 
		else
		{
			minfifo.pop_back();
			while (!minfifo.empty())
			{
				if (array[i] >= array[minfifo.back()])
					break;
			
				minfifo.pop_back();
			}
		}
		maxfifo.push_back(i);
		minfifo.push_back(i);
		if (i == width + maxfifo.front())
			maxfifo.pop_front();
		else 
			if (i == width + minfifo.front())
				minfifo.pop_front();
	}
	maxvalues[array.size() - width] = array[maxfifo.front()];
	minvalues[array.size() - width] = array[minfifo.front()];
}

/*
class simplelemiremaxmin: public minmaxfilter {
public:
    simplelemiremaxmin(vector<floattype> & array, uint width) :
        maxvalues(array.size() - width + 1),
        minvalues(array.size() - width + 1) 
		{
        deque<int> maxfifo, minfifo;
        maxfifo.push_back(0);
        minfifo.push_back(0);
        for (uint i = 1; i < width; ++i) {
            if (array[i] > array[i - 1]) { //overshoot
                maxfifo.pop_back();
                while (!maxfifo.empty()) {
                    if (array[i] <= array[maxfifo.back()])
                        break;
                    maxfifo.pop_back();
                }
            } else {
                minfifo.pop_back();
                while (!minfifo.empty()) {
                    if (array[i] >= array[minfifo.back()])
                        break;
                    minfifo.pop_back();
                }
            }
            maxfifo.push_back(i);
            minfifo.push_back(i);
        }
        for (uint i = width; i < array.size(); ++i) {
            maxvalues[i - width] = array[maxfifo.front()];
            minvalues[i - width] = array[minfifo.front()];
            if (array[i] > array[i - 1]) { //overshoot
                maxfifo.pop_back();
                while (!maxfifo.empty()) {
                    if (array[i] <= array[maxfifo.back()])
                        break;
                    maxfifo.pop_back();
                }
            } else {
                minfifo.pop_back();
                while (!minfifo.empty()) {
                    if (array[i] >= array[minfifo.back()])
                        break;
                    minfifo.pop_back();
                }
            }
            maxfifo.push_back(i);
            minfifo.push_back(i);
            if (i == width + maxfifo.front())
                maxfifo.pop_front();
            else if (i == width + minfifo.front())
                minfifo.pop_front();
        }
        maxvalues[array.size() - width] = array[maxfifo.front()];
        minvalues[array.size() - width] = array[minfifo.front()];
    }
    vector<floattype> & getmaxvalues() {
        return maxvalues;
    }
    vector<floattype> & getminvalues() {
        return minvalues;
    }
    vector<floattype> maxvalues;
    vector<floattype> minvalues;
};

*/