                 i: 1
                 count: 0
 
-        { swapped, i, count } = sort_context
+        { swapped, i } = sort_context
 
         if i == colours.length
                 sort_context.i = 1

                min: 0
                count: 0

        { i, j, count, min } = sort_context

        if j == colours.length
                swapRects(i-1, min)

                bsort()

qsort = (tukey) ->
        sort_context ?=
                median_stack: []
                in_partition: false
                pivot_ind: -1
                pivot_val: -1
                started_tukey_median: false
                started_partition: false

                from_stack: []
                to_stack: []

                from: 0
                to: colours.length - 1
                curr: 0

                count: 0

        { median_stack, in_partition, pivot_ind, pivot_val, started_tukey_median, from_stack, to_stack, from, to, curr, started_partition } = sort_context

        do_next = ->
                sort_context.count++

                if (sort_context.count % UPDATE_INTERVAL) == 0
                        defer(-> qsort(tukey))
                else
                        qsort(tukey)

        if median_stack.length > 0
                [ a, b, c, swap_count ] = median_stack[median_stack.length - 1]

                # Rename vars for clarity, as we want the median in a, not b.
                m0 = b
                m1 = a
                m2 = c

                if swap_count == 0
                        if colours[m1].val < colours[m0].val
                                swapRects(m1, m0)
                                # Increment count.
                                sort_context.median_stack[median_stack.length - 1][3]++
                        else
                                swap_count++

                if swap_count == 1
                        if colours[m2].val < colours[m1].val
                                swapRects(m2, m1)
                                # Increment count.
                                sort_context.median_stack[median_stack.length - 1][3]++
                        else
                                swap_count++

                if swap_count == 2
                        if colours[m1].val < colours[m0].val
                                swapRects(m1, m0)
                        else
                                swap_count++

                sort_context.median_stack.pop() if swap_count >= 2

                # If we swapped then (potentially) defer.
                if swap_count <= 2
                        do_next()
                        return

        if in_partition
                # We would have swapped pivot to end at start.
                while curr < to
                        if colours[curr].val <= pivot_val
                                swapRects(curr, pivot_ind)

                                sort_context.curr++
                                sort_context.pivot_ind++
                                do_next()
                                return

                        sort_context.curr++
                        curr = sort_context.curr

                # End of partition.
                sort_context.in_partition = false
                # Swap 'em back.
                swapRects(pivot_ind, to)
                do_next()
                return

        # OK we are out of the partition we are at the top level sort.

        # If we're done on this line then pop stack on next.
        if from >= to
                return if from_stack.length == 0

                sort_context.from = sort_context.from_stack.pop()
                sort_context.to = sort_context.to_stack.pop()
                sort_context.curr = sort_context.from
                sort_context.pivot_ind = -1

                sort_context.count-- # Shouldn't count towards swaps.
                do_next()
                return

        # Do we need to figure out the pivot index?
        if pivot_ind == -1
                mid = Math.floor(from + (to - from)/2)

                # Easy option first.
                if not tukey
                        # Do it this way to avoid overflow.
                        sort_context.pivot_ind = mid
                        pivot_ind = mid
                else if started_tukey_median
                        # Completed tukey median calculation.
                        sort_context.pivot_ind = from
                        pivot_ind = from
                        sort_context.started_tukey_median = false
                else
                        # OK kick off tukey median calculation.
                        sort_context.started_tukey_median = true

                        stack = []
                        # We do this last as stack so reverse order.
                        stack.push([from, mid, to - 1, 0])

                        if to - from > 40
                                s = Math.floor((to - from)/8)

                                # reverse order as stack.
                                stack.push([to - 1, to - 1 - s, to - 1 - 2 * s, 0])
                                stack.push([mid, mid - s, mid + s, 0])
                                stack.push([from, from + s, from + 2 * s, 0])

                        sort_context.median_stack = stack

                        # Handle this on next invocation.
                        sort_context.count-- # Shouldn't count towards swaps.
                        do_next()
                        return

        # OK we have a pivot index.

        # Did we start the partition?
        if not started_partition
                sort_context.started_partition = true
                sort_context.in_partition = true
                sort_context.curr = from

                sort_context.pivot_val = colours[pivot_ind].val

                # Put pivot at the end of the array.
                swapRects(pivot_ind, to)
                sort_context.pivot_ind = from

                # Handle this on next invocation.
                do_next()
                return

        # OK partition is done.
        sort_context.started_partition = false

        # Do lower half first, then push next on stack.
        sort_context.to = pivot_ind - 1
        sort_context.pivot_ind = -1
        sort_context.from_stack.push(pivot_ind + 1)
        sort_context.to_stack.push(to)

        # Handle this on next invocation.
        sort_context.count-- # Shouldn't count towards swaps.
        do_next()

# Heapsort
# Based on this Java implementation: http://git.io/heapsort
