Given an interval `start:stop`, make an iterator that returns for each
    level the first and last bin overlapping the interval, starting with the
    smallest bins.

    Zero-length intervals are binned according to the one-position interval
    following it.

    Algorithm by `Jim Kent
    <http://genomewiki.ucsc.edu/index.php/Bin_indexing_system>`_.

    :arg int start, stop: Interval positions (zero-based, open-ended).

    :return: Iterator yielding tuples `first, last` being the first and last
      bin overlapping with `start:stop`. The tuples are ordered according to
      the bin size of the levels, starting with the smallest bins.
    :rtype: iterator(tuple(int, int))

    :raise OutOfRangeError: If `start:stop` exceeds the range of the binning
      scheme.

def range_per_level(start, stop):
    """
    Given an interval `start:stop`, make an iterator that returns for each
    level the first and last bin overlapping the interval, starting with the
    smallest bins.

    Zero-length intervals are binned according to the one-position interval
    following it.

    Algorithm by `Jim Kent
    <http://genomewiki.ucsc.edu/index.php/Bin_indexing_system>`_.

    :arg int start, stop: Interval positions (zero-based, open-ended).

    :return: Iterator yielding tuples `first, last` being the first and last
      bin overlapping with `start:stop`. The tuples are ordered according to
      the bin size of the levels, starting with the smallest bins.
    :rtype: iterator(tuple(int, int))

    :raise OutOfRangeError: If `start:stop` exceeds the range of the binning
      scheme.
    """
    if start < 0 or stop > MAX_POSITION + 1:
        raise OutOfRangeError(
            'Interval %d:%d is out of range (maximum position is %d)'
            % (start, stop, MAX_POSITION))

    # Note that we treat the zero-length interval `x:x` as `x:x+1`.
    start_bin = start
    stop_bin = max(start, stop - 1)

    start_bin >>= SHIFT_FIRST
    stop_bin >>= SHIFT_FIRST

    for offset in BIN_OFFSETS:
        yield offset + start_bin, offset + stop_bin
        start_bin >>= SHIFT_NEXT
        stop_bin >>= SHIFT_NEXT