#include "sorter.h"

int partitioner(int* input, int p, int r) {
    int pivot = input[r];
    while (p < r) {
        while (input[p] < pivot)
            p++;
        while (input[r] > pivot) 
            r--;
        if (input[p] == input[r])
            p++;
        else if (p < r) {
        int tmp = input[p];
        input[p] = input[r];
        input[r] = tmp;
        }
    }
    return r;
}

void quicksort(int* input, int p, int r) {
    if ( p < r ) {
        int j = partitioner(input, p, r);        
        quicksort(input, p, j-1);
        quicksort(input, j+1, r);
    }
}

void sorter::sortAll(int data[], int size) {
    if(size == 0)
        return;
    quicksort(data, 0, size);
}

void sorter::sort(int data[], int size, int left, int right) {
    if(size == 0 || left < 0 || left >= size || right < 0 || right >= size)
        return;
    quicksort(data, left, right);
}

void sorter::medianOfThree(int data[], int size, int left, int right) {
    if(size == 0 || left < 0 || left >= size || right < 0 || right >= size || right < left)
        return;
    int l, m, r;
    l = data[left];
    r = data[right];
    m = data [(left + right)/2];
    if(l > m) {
        swap(data, size, left, (left + right)/2 );
        l = data[left];
        r = data[right];
        m = data [(left + right)/2];
    }
    if(l > r) {
        swap(data, size, left, right);
        l = data[left];
        r = data[right];
        m = data [(left + right)/2];
    }
    if(m > r) {
        swap(data, size, (left + right)/2 , right);
        l = data[left];
        r = data[right];
        m = data [(left + right)/2];
    }
}

int sorter::partition(int data[], int size, int left, int right) {
    if(size == 0 || left < 0 || left >= size || right < 0 || right >= size || right < left)
        return -1;
    if(size == 1) {
        return 0;
    }
    medianOfThree(data, size, 0, right);
    swap(data, size, 0, (right + left)/2);
    int l = 1;
    int r = size - 1;
    bool ltrue = false;
    bool rtrue = false;
    while(l <= r) {
        if(data[0] < data[l]) {
            ltrue = true;
        }
        else {
            l++;
        }
        if(data[0] > data[r]) {
            rtrue = true;
        }
        else {
            r--;
        }
        if(ltrue && rtrue) {
            rtrue = false;
            ltrue = false;
            swap(data, size, l, r);
        }
    }
    swap(data, size, 0, r);
    return r;
}

void sorter::swap(int data[], int size, int i, int j) {
    if(size == 0 || i < 0 || i >= size || j < 0 || j >= size)
        return;
    int temp = data[i];
    data[i] = data[j];
    data[j] = temp;
}
