const stack = [];

/**
 * @template T
 * @param {T[]|Uint32Array} data
 * @param {function(T,T):number} compare_function
 * @param {*} compare_function_context
 * @param {number} start
 * @param {number} end
 */
export function array_quick_sort_by_comparator(
    data,
    compare_function, compare_function_context,
    start, end
) {
    if (start >= end) {
        // section of 0 size, nothing to sort
        return;
    }

    let stackPointer = 2;
    let i, j;

    stack[0] = start;
    stack[1] = end;

    while (stackPointer > 0) {
        stackPointer -= 2;

        const right = stack[stackPointer + 1];
        const left = stack[stackPointer];

        i = left;
        j = right;

        const pivotIndex = (left + right) >> 1;

        const pivot = data[pivotIndex];

        /* partition */
        while (i <= j) {
            while (compare_function.call(compare_function_context, data[i], pivot) < 0) {
                i++;
            }

            while (compare_function.call(compare_function_context, data[j], pivot) > 0) {
                j--;
            }

            if (i <= j) {

                if (i !== j) {
                    //do swap
                    const tmp = data[i];
                    data[i] = data[j];
                    data[j] = tmp;

                }

                i++;
                j--;
            }
        }

        /* recursion */
        if (left < j) {
            stack[stackPointer++] = left;
            stack[stackPointer++] = j;
        }
        if (i < right) {
            stack[stackPointer++] = i;
            stack[stackPointer++] = right;
        }
    }
}