function _partition(&$elements, $p, $r, $fn)
{
    $x = $elements[$r];
    $i = $p - 1;
    for ($j = $p; $j <= $r - 1; $j++) {
        if ($fn($elements[$j], $x)) {
            $i = $i + 1;
            _swap_element($elements[$i], $elements[$j]);
        }
    }
    _swap_element($elements[$i + 1], $elements[$r]);
    return $i + 1;
}
/**
 * Reposition $elements[$i] into correct index based on heap property.
 * @param reference &$elements Reference to an array
 * @param int $i Index of particular element.
 * @return void
 */
function _max_heapify(&$elements, $i, $fn)
{
    global $_HEAP_SIZE;
    $l = _left_child($i);
    $r = _right_child($i);
    if ($l < $_HEAP_SIZE && $fn($elements[$l], $elements[$i])) {
        $largest = $l;
    } else {
        $largest = $i;
    }
    if ($r < $_HEAP_SIZE && $fn($elements[$r], $elements[$largest])) {
        $largest = $r;
    }
    if ($largest != $i) {
        _swap_element($elements[$i], $elements[$largest]);
        _max_heapify($elements, $largest, $fn);
    }
}